Skip to content

Commit dbfc9d9

Browse files
bnoordhuisrvagg
authored andcommitted
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. PR-URL: #5536 Reviewed-By: Rod Vagg <[email protected]>
1 parent 8fe68d7 commit dbfc9d9

11 files changed

+52
-154
lines changed

configure

-8
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,6 @@ parser.add_option('--without-ssl',
313313
dest='without_ssl',
314314
help='build without SSL')
315315

316-
parser.add_option('--without-ssl2',
317-
action='store_true',
318-
dest='ssl2',
319-
help='Disable SSL v2')
320-
321316
parser.add_option('--without-ssl3',
322317
action='store_true',
323318
dest='ssl3',
@@ -687,9 +682,6 @@ def configure_openssl(o):
687682
if options.without_ssl:
688683
return
689684

690-
if options.ssl2:
691-
o['defines'] += ['OPENSSL_NO_SSL2=1']
692-
693685
if options.ssl3:
694686
o['defines'] += ['OPENSSL_NO_SSL3=1']
695687

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/_tls_common.js

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

3838
if (!binding.SSL3_ENABLE)
3939
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv3;
40-
41-
if (!binding.SSL2_ENABLE)
42-
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv2;
4340
}
4441

4542
if (secureOptions === undefined) {

src/node.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -3012,7 +3012,6 @@ static void PrintHelp() {
30123012
" present.\n"
30133013
#endif
30143014
#endif
3015-
" --enable-ssl2 enable ssl2\n"
30163015
" --enable-ssl3 enable ssl3\n"
30173016
"\n"
30183017
"Environment variables:\n"
@@ -3083,7 +3082,9 @@ static void ParseArgs(int* argc,
30833082
exit(0);
30843083
} else if (strcmp(arg, "--enable-ssl2") == 0) {
30853084
#if HAVE_OPENSSL
3086-
SSL2_ENABLE = true;
3085+
fprintf(stderr,
3086+
"Error: --enable-ssl2 is no longer supported (CVE-2016-0800).\n");
3087+
exit(12);
30873088
#endif
30883089
} else if (strcmp(arg, "--enable-ssl3") == 0) {
30893090
#if HAVE_OPENSSL

src/node_crypto.cc

-14
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
7575

7676
namespace node {
7777

78-
bool SSL2_ENABLE = false;
7978
bool SSL3_ENABLE = false;
8079
bool ALLOW_INSECURE_SERVER_DHPARAM = false;
8180

@@ -317,23 +316,11 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
317316
const node::Utf8Value sslmethod(args[0]);
318317

319318
if (strcmp(*sslmethod, "SSLv2_method") == 0) {
320-
#ifndef OPENSSL_NO_SSL2
321-
method = SSLv2_method();
322-
#else
323319
return env->ThrowError("SSLv2 methods disabled");
324-
#endif
325320
} else if (strcmp(*sslmethod, "SSLv2_server_method") == 0) {
326-
#ifndef OPENSSL_NO_SSL2
327-
method = SSLv2_server_method();
328-
#else
329321
return env->ThrowError("SSLv2 methods disabled");
330-
#endif
331322
} else if (strcmp(*sslmethod, "SSLv2_client_method") == 0) {
332-
#ifndef OPENSSL_NO_SSL2
333-
method = SSLv2_client_method();
334-
#else
335323
return env->ThrowError("SSLv2 methods disabled");
336-
#endif
337324
} else if (strcmp(*sslmethod, "SSLv3_method") == 0) {
338325
#ifndef OPENSSL_NO_SSL3
339326
method = SSLv3_method();
@@ -5171,7 +5158,6 @@ void InitCrypto(Handle<Object> target,
51715158
EVP_PKEY_decrypt>);
51725159

51735160
NODE_DEFINE_CONSTANT(target, SSL3_ENABLE);
5174-
NODE_DEFINE_CONSTANT(target, SSL2_ENABLE);
51755161
}
51765162

51775163
} // namespace crypto

src/node_crypto.h

-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161

6262
namespace node {
6363

64-
extern bool SSL2_ENABLE;
6564
extern bool SSL3_ENABLE;
6665
extern bool ALLOW_INSECURE_SERVER_DHPARAM;
6766

src/node_crypto_clienthello.cc

+1-55
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ void ClientHelloParser::Parse(const uint8_t* data, size_t avail) {
3232
break;
3333
// Fall through
3434
case kTLSHeader:
35-
case kSSL2Header:
3635
ParseHeader(data, avail);
3736
break;
3837
case kPaused:
@@ -59,20 +58,8 @@ bool ClientHelloParser::ParseRecordHeader(const uint8_t* data, size_t avail) {
5958
state_ = kTLSHeader;
6059
body_offset_ = 5;
6160
} else {
62-
#ifdef OPENSSL_NO_SSL2
63-
frame_len_ = ((data[0] << 8) & kSSL2HeaderMask) + data[1];
64-
state_ = kSSL2Header;
65-
if (data[0] & kSSL2TwoByteHeaderBit) {
66-
// header without padding
67-
body_offset_ = 2;
68-
} else {
69-
// header with padding
70-
body_offset_ = 3;
71-
}
72-
#else
7361
End();
7462
return false;
75-
#endif // OPENSSL_NO_SSL2
7663
}
7764

7865
// Sanity check (too big frame, or too small)
@@ -85,12 +72,6 @@ bool ClientHelloParser::ParseRecordHeader(const uint8_t* data, size_t avail) {
8572
return true;
8673
}
8774

88-
#ifdef OPENSSL_NO_SSL2
89-
# define NODE_SSL2_VER_CHECK(buf) false
90-
#else
91-
# define NODE_SSL2_VER_CHECK(buf) ((buf)[0] == 0x00 && (buf)[1] == 0x02)
92-
#endif // OPENSSL_NO_SSL2
93-
9475

9576
void ClientHelloParser::ParseHeader(const uint8_t* data, size_t avail) {
9677
ClientHello hello;
@@ -101,22 +82,13 @@ void ClientHelloParser::ParseHeader(const uint8_t* data, size_t avail) {
10182

10283
// Skip unsupported frames and gather some data from frame
10384
// Check hello protocol version
104-
if (!(data[body_offset_ + 4] == 0x03 && data[body_offset_ + 5] <= 0x03) &&
105-
!NODE_SSL2_VER_CHECK(data + body_offset_ + 4)) {
85+
if (!(data[body_offset_ + 4] == 0x03 && data[body_offset_ + 5] <= 0x03))
10686
goto fail;
107-
}
10887

10988
if (data[body_offset_] == kClientHello) {
11089
if (state_ == kTLSHeader) {
11190
if (!ParseTLSClientHello(data, avail))
11291
goto fail;
113-
} else if (state_ == kSSL2Header) {
114-
#ifdef OPENSSL_NO_SSL2
115-
if (!ParseSSL2ClientHello(data, avail))
116-
goto fail;
117-
#else
118-
abort(); // Unreachable
119-
#endif // OPENSSL_NO_SSL2
12092
} else {
12193
// We couldn't get here, but whatever
12294
goto fail;
@@ -145,9 +117,6 @@ void ClientHelloParser::ParseHeader(const uint8_t* data, size_t avail) {
145117
}
146118

147119

148-
#undef NODE_SSL2_VER_CHECK
149-
150-
151120
void ClientHelloParser::ParseExtension(ClientHelloParser::ExtensionType type,
152121
const uint8_t* data,
153122
size_t len) {
@@ -270,27 +239,4 @@ bool ClientHelloParser::ParseTLSClientHello(const uint8_t* data, size_t avail) {
270239
}
271240

272241

273-
#ifdef OPENSSL_NO_SSL2
274-
bool ClientHelloParser::ParseSSL2ClientHello(const uint8_t* data,
275-
size_t avail) {
276-
const uint8_t* body;
277-
278-
// Skip header, version
279-
size_t session_offset = body_offset_ + 3;
280-
281-
if (session_offset + 4 < avail) {
282-
body = data + session_offset;
283-
284-
uint16_t ciphers_size = (body[0] << 8) + body[1];
285-
286-
if (body + 4 + ciphers_size < data + avail) {
287-
session_size_ = (body[2] << 8) + body[3];
288-
session_id_ = body + 4 + ciphers_size;
289-
}
290-
}
291-
292-
return true;
293-
}
294-
#endif // OPENSSL_NO_SSL2
295-
296242
} // namespace node

src/node_crypto_clienthello.h

-6
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ class ClientHelloParser {
8080
inline bool IsEnded() const;
8181

8282
private:
83-
static const uint8_t kSSL2TwoByteHeaderBit = 0x80;
84-
static const uint8_t kSSL2HeaderMask = 0x3f;
8583
static const size_t kMaxTLSFrameLen = 16 * 1024 + 5;
8684
static const size_t kMaxSSLExFrameLen = 32 * 1024;
8785
static const uint8_t kServernameHostname = 0;
@@ -91,7 +89,6 @@ class ClientHelloParser {
9189
enum ParseState {
9290
kWaiting,
9391
kTLSHeader,
94-
kSSL2Header,
9592
kPaused,
9693
kEnded
9794
};
@@ -120,9 +117,6 @@ class ClientHelloParser {
120117
const uint8_t* data,
121118
size_t len);
122119
bool ParseTLSClientHello(const uint8_t* data, size_t avail);
123-
#ifdef OPENSSL_NO_SSL2
124-
bool ParseSSL2ClientHello(const uint8_t* data, size_t avail);
125-
#endif // OPENSSL_NO_SSL2
126120

127121
ParseState state_;
128122
OnHelloCb onhello_cb_;

test/external/ssl-options/test.js

+1-64
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,30 +146,10 @@ function testSetupsCompatible(serverSetup, clientSetup) {
169146
return false;
170147
}
171148

172-
var ssl2Used = isSsl2Protocol(serverSetup.secureProtocol) ||
173-
isSsl2Protocol(clientSetup.secureProtocol);
174-
if (ssl2Used &&
175-
((serverSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS) ||
176-
(clientSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS))) {
177-
/*
178-
* Default ciphers are not compatible with SSLv2. Both client *and*
179-
* server need to specify a SSLv2 compatible cipher to be able to use
180-
* SSLv2.
181-
*/
182-
return false;
183-
}
184-
185149
return true;
186150
}
187151

188152
function sslSetupMakesSense(cmdLineOption, secureProtocol, secureOption) {
189-
if (isSsl2Protocol(secureProtocol)) {
190-
if (secureOption & constants.SSL_OP_NO_SSLv2 ||
191-
(secureOption == null && (!cmdLineOption || cmdLineOption.indexOf('--enable-ssl2') === -1))) {
192-
return false;
193-
}
194-
}
195-
196153
if (isSsl3Protocol(secureProtocol)) {
197154
if (secureOption & constants.SSL_OP_NO_SSLv3 ||
198155
(secureOption == null && (!cmdLineOption || cmdLineOption.indexOf('--enable-ssl3') === -1))) {
@@ -221,12 +178,6 @@ function createTestsSetups() {
221178
};
222179

223180
serversSetup.push(serverSetup);
224-
225-
if (isSsl2Protocol(serverSecureProtocol)) {
226-
var setupWithSsl2Ciphers = xtend(serverSetup);
227-
setupWithSsl2Ciphers.ciphers = SSL2_COMPATIBLE_CIPHERS;
228-
serversSetup.push(setupWithSsl2Ciphers);
229-
}
230181
}
231182
});
232183
});
@@ -243,12 +194,6 @@ function createTestsSetups() {
243194
};
244195

245196
clientsSetup.push(clientSetup);
246-
247-
if (isSsl2Protocol(clientSecureProtocol)) {
248-
var setupWithSsl2Ciphers = xtend(clientSetup);
249-
setupWithSsl2Ciphers.ciphers = SSL2_COMPATIBLE_CIPHERS;
250-
clientsSetup.push(setupWithSsl2Ciphers);
251-
}
252197
}
253198
});
254199
});
@@ -359,10 +304,6 @@ function stringToSecureOptions(secureOptionsString) {
359304

360305
var optionStrings = secureOptionsString.split('|');
361306
optionStrings.forEach(function (option) {
362-
if (option === 'SSL_OP_NO_SSLv2') {
363-
secureOptions |= constants.SSL_OP_NO_SSLv2;
364-
}
365-
366307
if (option === 'SSL_OP_NO_SSLv3') {
367308
secureOptions |= constants.SSL_OP_NO_SSLv3;
368309
}
@@ -422,10 +363,6 @@ function checkTestExitCode(testSetup, serverExitCode, clientExitCode) {
422363
function secureOptionsToString(secureOptions) {
423364
var secureOptsString = '';
424365

425-
if (secureOptions & constants.SSL_OP_NO_SSLv2) {
426-
secureOptsString += 'SSL_OP_NO_SSLv2';
427-
}
428-
429366
if (secureOptions & constants.SSL_OP_NO_SSLv3) {
430367
secureOptsString += '|SSL_OP_NO_SSLv3';
431368
}

0 commit comments

Comments
 (0)