8000 tls: add --tls-cipher-list command line switch · nodejs/node@5fef5c6 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 5fef5c6

Browse files
jasnellrvagg
authored andcommitted
tls: add --tls-cipher-list command line switch
This adds a new `--tls-cipher-list` command line switch that can be used to override the built-in default cipher list. The intent of this is to make it possible to enforce an alternative default cipher list at the process level. Overriding the default cipher list is still permitted at the application level by changing the value of `require('tls').DEFAULT_CIPHERS`. As part of the change, the built in default list is moved out of tls.js and into node_constants.h and node_constants.cc. Two new constants are added to require('constants'): * defaultCipherList (the active default cipher list) * defaultCoreCipherList (the built-in default cipher list) A test case and doc changes are included. A new NODE_DEFINE_STRING_CONSTANT macro is also created in node_internals.h When node_constants is initialized, it will pick up either the passed in command line switch or fallback to the default built-in suite. Within joyent/node, this change had originaly been wrapped up with a number of other related commits involving the removal of the RC4 cipher. This breaks out this isolated change. /cc @mhdawson, @misterdjules, @trevnorris, @indutny, @rvagg Reviewed By: Ben Noordhuis <ben@strongloop.com> PR-URL: #2412
1 parent c9867fe commit 5fef5c6

File tree

8 files changed

+144
-24
lines changed
  • lib
  • src
  • test/parallel
  • 8 files changed

    +144
    -24
    lines changed

    doc/api/tls.markdown

    Lines changed: 39 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -77,6 +77,44 @@ handshake extensions allowing you:
    7777
    * SNI - to use one TLS server for multiple hostnames with different SSL
    7878
    certificates.
    7979

    80+
    ## Modifying the Default TLS Cipher suite
    81+
    82+
    Node.js is built with a default suite of enabled and disabled TLS ciphers.
    83+
    Currently, the default cipher suite is:
    84+
    85+
    ECDHE-RSA-AES128-GCM-SHA256:
    86+
    ECDHE-ECDSA-AES128-GCM-SHA256:
    87+
    ECDHE-RSA-AES256-GCM-SHA384:
    88+
    ECDHE-ECDSA-AES256-GCM-SHA384:
    89+
    DHE-RSA-AES128-GCM-SHA256:
    90+
    ECDHE-RSA-AES128-SHA256:
    91+
    DHE-RSA-AES128-SHA256:
    92+
    ECDHE-RSA-AES256-SHA384:
    93+
    DHE-RSA-AES256-SHA384:
    94+
    ECDHE-RSA-AES256-SHA256:
    95+
    DHE-RSA-AES256-SHA256:
    96+
    HIGH:
    97+
    !aNULL:
    98+
    !eNULL:
    99+
    !EXPORT:
    100+
    !DES:
    101+
    !RC4:
    102+
    !MD5:
    103+
    !PSK:
    104+
    !SRP:
    105+
    !CAMELLIA
    106+
    107+
    This default can be overriden entirely using the `--tls-cipher-list` command
    108+
    line switch. For instance, the following makes
    109+
    `ECDHE-RSA-AES128-GCM-SHA256:!RC4` the default TLS cipher suite:
    110+
    111+
    node --tls-cipher-list="ECDHE-RSA-AES128-GCM-SHA256:!RC4"
    112+
    113+
    Note that the default cipher suite included within Node.js has been carefully
    114+
    selected to reflect current security best practices and risk mitigation.
    115+
    Changing the default cipher suite can have a significant impact on the security
    116+
    of an application. The `--tls-cipher-list` switch should by used only if
    117+
    absolutely necessary.
    80118

    81119
    ## Perfect Forward Secrecy
    82120

    @@ -138,7 +176,7 @@ automatically set as a listener for the [secureConnection][] event. The
    138176
    - `crl` : Either a string or list of strings of PEM encoded CRLs (Certificate
    139177
    Revocation List)
    140178

    141-
    - `ciphers`: A string describing the ciphers to use or exclude, seperated by
    179+
    - `ciphers`: A string describing the ciphers to use or exclude, separated by
    142180
    `:`. The default cipher suite is:
    143181

    144182
    ECDHE-RSA-AES128-GCM-SHA256:

    doc/iojs.1

    Lines changed: 3 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -64,6 +64,9 @@ and servers.
    6464

    6565
    --v8-options print v8 command line options
    6666

    67+
    --tls-cipher-list=list use an alternative default TLS cipher list
    68+
    (available only when Node.js is built with
    69+
    OpenSSL and crypto support enabled)
    6770

    6871
    .SH ENVIRONMENT VARIABLES
    6972

    lib/tls.js

    Lines changed: 2 additions & 23 deletions
    Original file line numberDiff line numberDiff line change
    @@ -5,6 +5,7 @@ const url = require('url');
    55
    const util = require('util');
    66
    const binding = process.binding('crypto');
    77
    const Buffer = require('buffer').Buffer;
    8+
    const constants = require('constants');
    89

    910
    // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations
    1011
    // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more
    @@ -15,29 +16,7 @@ exports.CLIENT_RENEG_WINDOW = 600;
    1516

    1617
    exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024;
    1718

    18-
    exports.DEFAULT_CIPHERS = [
    19-
    'ECDHE-RSA-AES128-GCM-SHA256',
    20-
    'ECDHE-ECDSA-AES128-GCM-SHA256',
    21-
    'ECDHE-RSA-AES256-GCM-SHA384',
    22-
    'ECDHE-ECDSA-AES256-GCM-SHA384',
    23-
    'DHE-RSA-AES128-GCM-SHA256',
    24-
    'ECDHE-RSA-AES128-SHA256',
    25-
    'DHE-RSA-AES128-SHA256',
    26-
    'ECDHE-RSA-AES256-SHA384',
    27-
    'DHE-RSA-AES256-SHA384',
    28-
    'ECDHE-RSA-AES256-SHA256',
    29-
    'DHE-RSA-AES256-SHA256',
    30-
    'HIGH',
    31-
    '!aNULL',
    32-
    '!eNULL',
    33-
    '!EXPORT',
    34-
    '!DES',
    35-
    '!RC4',
    36-
    '!MD5',
    37-
    '!PSK',
    38-
    '!SRP',
    39-
    '!CAMELLIA'
    40-
    ].join(':');
    19+
    exports.DEFAULT_CIPHERS = constants.defaultCipherList;
    4120

    4221
    exports.DEFAULT_ECDH_CURVE = 'prime256v1';
    4322

    src/node.cc

    Lines changed: 7 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -3111,6 +3111,9 @@ static void PrintHelp() {
    31113111
    " --track-heap-objects track heap object allocations for heap "
    31123112
    "snapshots\n"
    31133113
    " --v8-options print v8 command line options\n"
    3114+
    #if HAVE_OPENSSL
    3115+
    " --tls-cipher-list=val use an alternative default TLS cipher list\n"
    3116+
    #endif
    31143117
    #if defined(NODE_HAVE_I18N_SUPPORT)
    31153118
    " --icu-data-dir=dir set ICU data load path to dir\n"
    31163119
    " (overrides NODE_ICU_DATA)\n"
    @@ -3242,6 +3245,10 @@ static void ParseArgs(int* argc,
    32423245
    } else if (strcmp(arg, "--v8-options") == 0) {
    32433246
    new_v8_argv[new_v8_argc] = "--help";
    32443247
    new_v8_argc += 1;
    3248+
    #if HAVE_OPENSSL
    3249+
    } else if (strncmp(arg, "--tls-cipher-list=", 18) == 0) {
    3250+
    default_cipher_list = arg + 18;
    3251+
    #endif
    32453252
    #if defined(NODE_HAVE_I18N_SUPPORT)
    32463253
    } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) {
    32473254
    icu_data_dir = arg + 15;

    src/node_constants.cc

    Lines changed: 16 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -24,6 +24,10 @@ namespace node {
    2424
    using v8::Handle;
    2525
    using v8::Object;
    2626

    27+
    #if HAVE_OPENSSL
    28+
    const char* default_cipher_list = DEFAULT_CIPHER_LIST_CORE;
    29+
    #endif
    30+
    2731
    void DefineErrnoConstants(Handle<Object> target) {
    2832
    #ifdef E2BIG
    2933
    NODE_DEFINE_CONSTANT(target, E2BIG);
    @@ -1108,13 +1112,25 @@ void DefineUVConstants(Handle<Object> target) {
    11081112
    NODE_DEFINE_CONSTANT(target, UV_UDP_REUSEADDR);
    11091113
    }
    11101114

    1115+
    void DefineCryptoConstants(Handle<Object> target) {
    1116+
    #if HAVE_OPENSSL
    1117+
    NODE_DEFINE_STRING_CONSTANT(target,
    1118+
    "defaultCoreCipherList",
    1119+
    DEFAULT_CIPHER_LIST_CORE);
    1120+
    NODE_DEFINE_STRING_CONSTANT(target,
    1121+
    "defaultCipherList",
    1122+
    default_cipher_list);
    1123+
    #endif
    1124+
    }
    1125+
    11111126
    void DefineConstants(Handle<Object> target) {
    11121127
    DefineErrnoConstants(target);
    11131128
    DefineWindowsErrorConstants(target);
    11141129
    DefineSignalConstants(target);
    11151130
    DefineOpenSSLConstants(target);
    11161131
    DefineSystemConstants(target);
    11171132
    DefineUVConstants(target);
    1133+
    DefineCryptoConstants(target);
    11181134
    }
    11191135

    11201136
    } // namespace node

    src/node_constants.h

    Lines changed: 29 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -4,7 +4,36 @@
    44
    #include "node.h"
    55
    #include "v8.h"
    66

    7+
    #if HAVE_OPENSSL
    8+
    #define DEFAULT_CIPHER_LIST_CORE "ECDHE-RSA-AES128-GCM-SHA256:" \
    9+
    "ECDHE-ECDSA-AES128-GCM-SHA256:" \
    10+
    "ECDHE-RSA-AES256-GCM-SHA384:" \
    11+
    "ECDHE-ECDSA-AES256-GCM-SHA384:" \
    12+
    "DHE-RSA-AES128-GCM-SHA256:" \
    13+
    "ECDHE-RSA-AES128-SHA256:" \
    14+
    "DHE-RSA-AES128-SHA256:" \
    15+
    "ECDHE-RSA-AES256-SHA384:" \
    16+
    "DHE-RSA-AES256-SHA384:" \
    17+
    "ECDHE-RSA-AES256-SHA256:" \
    18+
    "DHE-RSA-AES256-SHA256:" \
    19+
    "HIGH:" \
    20+
    "!aNULL:" \
    21+
    "!eNULL:" \
    22+
    "!EXPORT:" \
    23+
    "!DES:" \
    24+
    "!RC4:" \
    25+
    "!MD5:" \
    26+
    "!PSK:" \
    27+
    "!SRP:" \
    28+
    "!CAMELLIA"
    29+
    #endif
    30+
    731
    namespace node {
    32+
    33+
    #if HAVE_OPENSSL
    34+
    extern const char* default_cipher_list;
    35+
    #endif
    36+
    837
    void DefineConstants(v8::Handle<v8::Object> target);
    938
    } // namespace node
    1039

    src/node_internals.h

    Lines changed: 16 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -12,6 +12,22 @@
    1212

    1313
    struct sockaddr;
    1414

    15+
    // Variation on NODE_DEFINE_CONSTANT that sets a String value.
    16+
    #define NODE_DEFINE_STRING_CONSTANT(target, name, constant) \
    17+
    do { \
    18+
    v8::Isolate* isolate = target->GetIsolate(); \
    19+
    v8::Local<v8::String> constant_name = \
    20+
    v8::String::NewFromUtf8(isolate, name); \
    21+
    v8::Local<v8::String> constant_value = \
    22+
    v8::String::NewFromUtf8(isolate, constant); \
    23+
    v8::PropertyAttribute constant_attributes = \
    24+
    static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete); \
    25+
    target->ForceSet(isolate->GetCurrentContext(), \
    26+
    constant_name, \
    27+
    constant_value, \
    28+
    constant_attributes); \
    29+
    } while (0)
    30+
    1531
    namespace node {
    1632

    1733
    // Forward declaration
    Lines changed: 32 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,32 @@
    1+
    'use strict';
    2+
    const common = require('../common');
    3+
    4+
    if (!common.hasCrypto) {
    5+
    console.log('1..0 # Skipped: missing crypto');
    6+
    return;
    7+
    }
    8+
    9+
    const assert = require('assert');
    10+
    const spawn = require('child_process').spawn;
    11+
    const defaultCoreList = require('constants').defaultCoreCipherList;
    12+
    13+
    function doCheck(arg, check) {
    14+
    var out = '';
    15+
    var arg = arg.concat([
    16+
    '-pe',
    17+
    'require("constants").defaultCipherList'
    18+
    ]);
    19+
    spawn(process.execPath, arg, {}).
    20+
    on('error', assert.fail).
    21+
    stdout.on('data', function(chunk) {
    22+
    out += chunk;
    23+
    }).on('end', function() {
    24+
    assert.equal(out.trim(), check);
    25+
    }).on('error', assert.fail);
    26+
    }
    27+
    28+
    // test the default unmodified version
    29+
    doCheck([], defaultCoreList);
    30+
    31+
    // test the command line switch by itself
    32+
    doCheck(['--tls-cipher-list=ABC'], 'ABC');

    0 commit comments

    Comments
     (0)
    0