Skip to content

Commit f8cb0dc

Browse files
committed
crypto,tls: remove SSLv2 support
Remove support for SSLv2 because of DROWN (CVE-2016-0800). Use of the `--enable-ssl2` flag is now an error; node will print an error message and exit. Fixes: nodejs/Release#80 PR-URL: #5529 Reviewed-By: Rod Vagg <rod@vagg.org>
1 parent e483f3f commit f8cb0dc

File tree

9 files changed

+51
-103
lines changed

9 files changed

+51
-103
lines changed

configure

-8
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,6 @@ parser.add_option("--systemtap-includes",
112112
dest="systemtap_includes",
113113
help=optparse.SUPPRESS_HELP)
114114

115-
parser.add_option("--without-ssl2",
116-
action="store_true",
117-
dest="ssl2",
118-
help="Disable SSL v2")
119-
120115
parser.add_option("--without-ssl3",
121116
action="store_true",
122117
dest="ssl3",
@@ -632,9 +627,6 @@ def configure_openssl(o):
632627
if options.without_ssl:
633628
return
634629

635-
if options.ssl2:
636-
o['defines'] += ['OPENSSL_NO_SSL2=1']
637-
638630
if options.ssl3:
639631
o['defines'] += ['OPENSSL_NO_SSL3=1']
640632

deps/openssl/openssl.gyp

+7-1
Original file line numberDiff line numberDiff line change
@@ -1093,13 +1093,19 @@
10931093
'L_ENDIAN',
10941094
'PURIFY',
10951095
'_REENTRANT',
1096-
1096+
'OPENSSL_NO_SSL2',
10971097
# Heartbeat is a TLS extension, that couldn't be turned off or
10981098
# asked to be not advertised. Unfortunately this is unacceptable for
10991099
# Microsoft's IIS, which seems to be ignoring whole ClientHello after
11001100
# seeing this extension.
11011101
'OPENSSL_NO_HEARTBEATS',
11021102
],
1103+
'direct_dependent_settings': {
1104+
'defines': [
1105+
'OPENSSL_NO_SSL2',
1106+
'OPENSSL_NO_HEARTBEATS',
1107+
],
1108+
},
11031109
'conditions': [
11041110
['OS=="win"', {
11051111
'defines': [

lib/crypto.js

-3
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ function getSecureOptions(secureProtocol, secureOptions) {
6767

6868
if (!binding.SSL3_ENABLE)
6969
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv3;
70-
71-
if (!binding.SSL2_ENABLE)
72-
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv2;
7370
}
7471

7572
if (secureOptions === undefined) {

src/node.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -2637,7 +2637,6 @@ static void PrintHelp() {
26372637
" --v8-options print v8 command line options\n"
26382638
" --max-stack-size=val set max v8 stack size (bytes)\n"
26392639
#if HAVE_OPENSSL
2640-
" --enable-ssl2 enable ssl2\n"
26412640
" --enable-ssl3 enable ssl3\n"
26422641
#endif
26432642
"\n"
@@ -2675,8 +2674,9 @@ static void ParseArgs(int argc, char **argv) {
26752674
argv[i] = const_cast<char*>("");
26762675
#if HAVE_OPENSSL
26772676
} else if (strcmp(arg, "--enable-ssl2") == 0) {
2678-
SSL2_ENABLE = true;
2679-
argv[i] = const_cast<char*>("");
2677+
fprintf(stderr,
2678+
"Error: --enable-ssl2 is no longer supported (CVE-2016-0800).\n");
2679+
exit(12);
26802680
} else if (strcmp(arg, "--enable-ssl3") == 0) {
26812681
SSL3_ENABLE = true;
26822682
argv[i] = const_cast<char*>("");

src/node_crypto.cc

-14
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ const char* root_certs[] = {
6969
NULL
7070
};
7171

72-
bool SSL2_ENABLE = false;
7372
bool SSL3_ENABLE = false;
7473

7574
namespace crypto {
@@ -242,23 +241,11 @@ Handle<Value> SecureContext::Init(const Arguments& args) {
242241
node::Utf8Value sslmethod(args[0]);
243242

244243
if (strcmp(*sslmethod, "SSLv2_method") == 0) {
245-
#ifndef OPENSSL_NO_SSL2
246-
method = SSLv2_method();
247-
#else
248244
return ThrowException(Exception::Error(String::New("SSLv2 methods disabled")));
249-
#endif
250245
} else if (strcmp(*sslmethod, "SSLv2_server_method") == 0) {
251-
#ifndef OPENSSL_NO_SSL2
252-
method = SSLv2_server_method();
253-
#else
254246
return ThrowException(Exception::Error(String::New("SSLv2 methods disabled")));
255-
#endif
256247
} else if (strcmp(*sslmethod, "SSLv2_client_method") == 0) {
257-
#ifndef OPENSSL_NO_SSL2
258-
method = SSLv2_client_method();
259-
#else
260248
return ThrowException(Exception::Error(String::New("SSLv2 methods disabled")));
261-
#endif
262249
} else if (strcmp(*sslmethod, "SSLv3_method") == 0) {
263250
#ifndef OPENSSL_NO_SSL3
264251
method = SSLv3_method();
@@ -4256,7 +4243,6 @@ void InitCrypto(Handle<Object> target) {
42564243
ext_key_usage_symbol = NODE_PSYMBOL("ext_key_usage");
42574244

42584245
NODE_DEFINE_CONSTANT(target, SSL3_ENABLE);
4259-
NODE_DEFINE_CONSTANT(target, SSL2_ENABLE);
42604246
}
42614247

42624248
} // namespace crypto

src/node_crypto.h

-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545

4646
namespace node {
4747

48-
extern bool SSL2_ENABLE;
4948
extern bool SSL3_ENABLE;
5049

5150
namespace crypto {

test/external/ssl-options/test.js

+1-73
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,17 @@ var debug = require('debug')('test-node-ssl');
1111

1212
var common = require('../../common');
1313

14-
var SSL2_COMPATIBLE_CIPHERS = 'RC4-MD5';
15-
16-
var CMD_LINE_OPTIONS = [ null, "--enable-ssl2", "--enable-ssl3" ];
14+
var CMD_LINE_OPTIONS = [ null, "--enable-ssl3" ];
1715

1816
var SERVER_SSL_PROTOCOLS = [
1917
null,
20-
'SSLv2_method', 'SSLv2_server_method',
2118
'SSLv3_method', 'SSLv3_server_method',
2219
'TLSv1_method', 'TLSv1_server_method',
2320
'SSLv23_method','SSLv23_server_method'
2421
];
2522

2623
var CLIENT_SSL_PROTOCOLS = [
2724
null,
28-
'SSLv2_method', 'SSLv2_client_method',
2925
'SSLv3_method', 'SSLv3_client_method',
3026
'TLSv1_method', 'TLSv1_client_method',
3127
'SSLv23_method','SSLv23_client_method'
@@ -34,9 +30,7 @@ var CLIENT_SSL_PROTOCOLS = [
3430
var SECURE_OPTIONS = [
3531
null,
3632
0,
37-
constants.SSL_OP_NO_SSLv2,
3833
constants.SSL_OP_NO_SSLv3,
39-
constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3
4034
];
4135

4236
function xtend(source) {
@@ -105,30 +99,13 @@ function isSsl3Protocol(secureProtocol) {
10599
secureProtocol === 'SSLv3_server_method';
106100
}
107101

108-
function isSsl2Protocol(secureProtocol) {
109-
assert(secureProtocol === null || typeof secureProtocol === 'string');
110-
111-
return secureProtocol === 'SSLv2_method' ||
112-
secureProtocol === 'SSLv2_client_method' ||
113-
secureProtocol === 'SSLv2_server_method';
114-
}
115-
116102
function secureProtocolCompatibleWithSecureOptions(secureProtocol, secureOptions, cmdLineOption) {
117103
if (secureOptions == null) {
118-
if (isSsl2Protocol(secureProtocol) &&
119-
(!cmdLineOption || cmdLineOption.indexOf('--enable-ssl2') === -1)) {
120-
return false;
121-
}
122-
123104
if (isSsl3Protocol(secureProtocol) &&
124105
(!cmdLineOption || cmdLineOption.indexOf('--enable-ssl3') === -1)) {
125106
return false;
126107
}
127108
} else {
128-
if (secureOptions & constants.SSL_OP_NO_SSLv2 && isSsl2Protocol(secureProtocol)) {
129-
return false;
130-
}
131-
132109
if (secureOptions & constants.SSL_OP_NO_SSLv3 && isSsl3Protocol(secureProtocol)) {
133110
return false;
134111
}
@@ -169,39 +146,10 @@ function testSetupsCompatible(serverSetup, clientSetup) {
169146
return false;
170147
}
171148

172-
if (isSsl2Protocol(serverSetup.secureProtocol) ||
173-
isSsl2Protocol(clientSetup.secureProtocol)) {
174-
175-
/*
176-
* It seems that in order to be able to use SSLv2, at least the server
177-
* *needs* to advertise at least one cipher compatible with it.
178-
*/
179-
if (serverSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS) {
180-
return false;
181-
}
182-
183-
/*
184-
* If only either one of the client or server specify SSLv2 as their
185-
* protocol, then *both* of them *need* to advertise at least one cipher
186-
* that is compatible with SSLv2.
187-
*/
188-
if ((!isSsl2Protocol(serverSetup.secureProtocol) || !isSsl2Protocol(clientSetup.secureProtocol)) &&
189-
(clientSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS || serverSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS)) {
190-
return false;
191-
}
192-
}
193-
194149
return true;
195150
}
196151

197152
function sslSetupMakesSense(cmdLineOption, secureProtocol, secureOption) {
198-
if (isSsl2Protocol(secureProtocol)) {
199-
if (secureOption & constants.SSL_OP_NO_SSLv2 ||
200-
(secureOption == null && (!cmdLineOption || cmdLineOption.indexOf('--enable-ssl2') === -1))) {
201-
return false;
202-
}
203-
}
204-
205153
if (isSsl3Protocol(secureProtocol)) {
206154
if (secureOption & constants.SSL_OP_NO_SSLv3 ||
207155
(secureOption == null && (!cmdLineOption || cmdLineOption.indexOf('--enable-ssl3') === -1))) {
@@ -230,12 +178,6 @@ function createTestsSetups() {
230178
};
231179

232180
serversSetup.push(serverSetup);
233-
234-
if (isSsl2Protocol(serverSecureProtocol)) {
235-
var setupWithSsl2Ciphers = xtend(serverSetup);
236-
setupWithSsl2Ciphers.ciphers = SSL2_COMPATIBLE_CIPHERS;
237-
serversSetup.push(setupWithSsl2Ciphers);
238-
}
239181
}
240182
});
241183
});
@@ -252,12 +194,6 @@ function createTestsSetups() {
252194
};
253195

254196
clientsSetup.push(clientSetup);
255-
256-
if (isSsl2Protocol(clientSecureProtocol)) {
257-
var setupWithSsl2Ciphers = xtend(clientSetup);
258-
setupWithSsl2Ciphers.ciphers = SSL2_COMPATIBLE_CIPHERS;
259-
clientsSetup.push(setupWithSsl2Ciphers);
260-
}
261197
}
262198
});
263199
});
@@ -367,10 +303,6 @@ function stringToSecureOptions(secureOptionsString) {
367303

368304
var optionStrings = secureOptionsString.split('|');
369305
optionStrings.forEach(function (option) {
370-
if (option === 'SSL_OP_NO_SSLv2') {
371-
secureOptions |= constants.SSL_OP_NO_SSLv2;
372-
}
373-
374306
if (option === 'SSL_OP_NO_SSLv3') {
375307
secureOptions |= constants.SSL_OP_NO_SSLv3;
376308
}
@@ -430,10 +362,6 @@ function checkTestExitCode(testSetup, serverExitCode, clientExitCode) {
430362
function secureOptionsToString(secureOptions) {
431363
var secureOptsString = '';
432364

433-
if (secureOptions & constants.SSL_OP_NO_SSLv2) {
434-
secureOptsString += 'SSL_OP_NO_SSLv2';
435-
}
436-
437365
if (secureOptions & constants.SSL_OP_NO_SSLv3) {
438366
secureOptsString += '|SSL_OP_NO_SSLv3';
439367
}

test/simple/test-tls-enable-ssl2.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
var common = require('../common');
4+
var assert = require('assert');
5+
var spawn = require('child_process').spawn;
6+
7+
var stdout = '';
8+
var stderr = '';
9+
var proc = spawn(process.execPath, ['--enable-ssl2', '-e', '0']);
10+
proc.stdout.setEncoding('utf8');
11+
proc.stderr.setEncoding('utf8');
12+
proc.stdout.on('data', function(data) { stdout += data; });
13+
proc.stderr.on('data', function(data) { stderr += data; });
14+
proc.on('exit', common.mustCall(function(exitCode, signalCode) {
15+
assert.strictEqual(exitCode, 12);
16+
assert.strictEqual(signalCode, null);
17+
}));
18+
process.on('exit', function() {
19+
assert.strictEqual(stdout, '');
20+
assert(/Error: --enable-ssl2 is no longer supported/.test(stderr));
21+
});

test/simple/test-tls-ssl2-methods.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
var common = require('../common');
4+
var assert = require('assert');
5+
6+
try {
7+
var crypto = require('crypto');
8+
} catch (e) {
9+
console.log('1..0 # Skipped: missing crypto');
10+
return;
11+
}
12+
13+
var methods = ['SSLv2_method', 'SSLv2_client_method', 'SSLv2_server_method'];
14+
15+
methods.forEach(function(method) {
16+
assert.throws(function() {
17+
crypto.createCredentials({ secureProtocol: method });
18+
}, /SSLv2 methods disabled/);
19+
});

0 commit comments

Comments
 (0)