Browse Source

crypto: allow forcing SSLv2/v3 via secureProtocol

Force-enable SSLv2/v3 when `secureProtocol` is explicitly set
to `SSLv2_method` or `SSLv3_method`.

see discussion at #8551
v0.10.33-release
Fedor Indutny 10 years ago
committed by Timothy J Fontaine
parent
commit
1349b680ba
  1. 22
      doc/api/tls.markdown
  2. 10
      lib/crypto.js
  3. 24
      src/node_crypto.cc
  4. 53
      test/simple/test-tls-disable-ssl2.js
  5. 53
      test/simple/test-tls-disable-ssl3.js
  6. 55
      test/simple/test-tls-enable-ssl2.js
  7. 55
      test/simple/test-tls-enable-ssl3.js

22
doc/api/tls.markdown

@ -48,15 +48,19 @@ If you wish to enable SSLv2 or SSLv3, run node with the `--enable-ssl2` or
`--enable-ssl3` flag respectively. In future versions of Node.js SSLv2 and
SSLv3 will not be compiled in by default.
This means that without having one or both of those flags set on the command
line, Node.js will **throw** if you explicitly set the `secureProtocol` to
`SSLv3_method` or similar. However the default protocol method Node.js uses is
`SSLv23_method` which would be more accurately named `AutoNegotiate_method`.
This method will try and negotiate from the highest level down to whatever the
client supports. To provide a secure default, Node.js (since v0.10.33)
explicitly disables the use of SSLv3 and SSLv2 by setting the `secureOptions`
to be `SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2` (again, unless you have passed
`--enable-ssl3` or `--enable-ssl2`).
There is a way to force node into using SSLv3 or SSLv2 only mode by explicitly
specifying `secureProtocol` to `'SSLv3_method'` or `'SSLv2_method'`.
The default protocol method Node.js uses is `SSLv23_method` which would be more
accurately named `AutoNegotiate_method`. This method will try and negotiate
from the highest level down to whatever the client supports. To provide a
secure default, Node.js (since v0.10.33) explicitly disables the use of SSLv3
and SSLv2 by setting the `secureOptions` to be
`SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2` (again, unless you have passed
`--enable-ssl3`, or `--enable-ssl2`, or `SSLv3_method` as `secureProtocol`).
If you have set `securityOptions` to anything, we will not override your
options.
The ramifications of this behavior change:

10
lib/crypto.js

@ -92,8 +92,14 @@ function Credentials(secureProtocol, flags, context) {
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv2;
}
if (flags === undefined)
flags = CONTEXT_DEFAULT_OPTIONS;
if (flags === undefined) {
if (secureProtocol === undefined ||
secureProtocol === 'SSLv23_method' ||
secureProtocol === 'SSLv23_server_method' ||
secureProtocol === 'SSLv23_client_method') {
flags |= CONTEXT_DEFAULT_OPTIONS;
}
}
this.context.setOptions(flags);
}

24
src/node_crypto.cc

@ -238,24 +238,6 @@ Handle<Value> SecureContext::New(const Arguments& args) {
}
bool MaybeThrowSSL3() {
if (!SSL3_ENABLE) {
ThrowException(Exception::Error(String::New("SSLv3 is considered unsafe, see node --help")));
return true;
} else {
return false;
}
}
bool MaybeThrowSSL2() {
if (!SSL2_ENABLE) {
ThrowException(Exception::Error(String::New("SSLv2 is considered unsafe, see node --help")));
return true;
} else {
return false;
}
}
Handle<Value> SecureContext::Init(const Arguments& args) {
HandleScope scope;
@ -268,42 +250,36 @@ Handle<Value> SecureContext::Init(const Arguments& args) {
if (strcmp(*sslmethod, "SSLv2_method") == 0) {
#ifndef OPENSSL_NO_SSL2
if (MaybeThrowSSL2()) return Undefined();
method = SSLv2_method();
#else
return ThrowException(Exception::Error(String::New("SSLv2 methods disabled")));
#endif
} else if (strcmp(*sslmethod, "SSLv2_server_method") == 0) {
#ifndef OPENSSL_NO_SSL2
if (MaybeThrowSSL2()) return Undefined();
method = SSLv2_server_method();
#else
return ThrowException(Exception::Error(String::New("SSLv2 methods disabled")));
#endif
} else if (strcmp(*sslmethod, "SSLv2_client_method") == 0) {
#ifndef OPENSSL_NO_SSL2
if (MaybeThrowSSL2()) return Undefined();
method = SSLv2_client_method();
#else
return ThrowException(Exception::Error(String::New("SSLv2 methods disabled")));
#endif
} else if (strcmp(*sslmethod, "SSLv3_method") == 0) {
#ifndef OPENSSL_NO_SSL3
if (MaybeThrowSSL3()) return Undefined();
method = SSLv3_method();
#else
return ThrowException(Exception::Error(String::New("SSLv3 methods disabled")));
#endif
} else if (strcmp(*sslmethod, "SSLv3_server_method") == 0) {
#ifndef OPENSSL_NO_SSL3
if (MaybeThrowSSL3()) return Undefined();
method = SSLv3_server_method();
#else
return ThrowException(Exception::Error(String::New("SSLv3 methods disabled")));
#endif
} else if (strcmp(*sslmethod, "SSLv3_client_method") == 0) {
#ifndef OPENSSL_NO_SSL3
if (MaybeThrowSSL3()) return Undefined();
method = SSLv3_client_method();
#else
return ThrowException(Exception::Error(String::New("SSLv3 methods disabled")));

53
test/simple/test-tls-disable-ssl2.js

@ -1,53 +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 common = require('../common');
var assert = require('assert');
var tls = require('tls');
var fs = require('fs');
var SSL_Method = 'SSLv2_method';
var localhost = '127.0.0.1';
function test(honorCipherOrder, clientCipher, expectedCipher, cb) {
var soptions = {
secureProtocol: SSL_Method,
key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'),
ciphers: 'AES256-SHA:RC4-SHA:DES-CBC-SHA',
honorCipherOrder: !!honorCipherOrder
};
var server;
assert.throws(function() {
server = tls.createServer(soptions, function(cleartextStream) {
nconns++;
});
}, /SSLv2 is considered unsafe/);
}
test1();
function test1() {
// Client has the preference of cipher suites by default
test(false, 'DES-CBC-SHA:RC4-SHA:AES256-SHA','DES-CBC-SHA');
}

53
test/simple/test-tls-disable-ssl3.js

@ -1,53 +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 common = require('../common');
var assert = require('assert');
var tls = require('tls');
var fs = require('fs');
var SSL_Method = 'SSLv3_method';
var localhost = '127.0.0.1';
function test(honorCipherOrder, clientCipher, expectedCipher, cb) {
var soptions = {
secureProtocol: SSL_Method,
key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'),
ciphers: 'AES256-SHA:RC4-SHA:DES-CBC-SHA',
honorCipherOrder: !!honorCipherOrder
};
var server;
assert.throws(function() {
server = tls.createServer(soptions, function(cleartextStream) {
nconns++;
});
}, /SSLv3 is considered unsafe/);
}
test1();
function test1() {
// Client has the preference of cipher suites by default
test(false, 'DES-CBC-SHA:RC4-SHA:AES256-SHA','DES-CBC-SHA');
}

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

@ -1,55 +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.
// Flags: --enable-ssl2
var common = require('../common');
var assert = require('assert');
var tls = require('tls');
var fs = require('fs');
var SSL_Method = 'SSLv2_method';
var localhost = '127.0.0.1';
function test(honorCipherOrder, clientCipher, expectedCipher, cb) {
var soptions = {
secureProtocol: SSL_Method,
key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'),
ciphers: 'AES256-SHA:RC4-SHA:DES-CBC-SHA',
honorCipherOrder: !!honorCipherOrder
};
var server;
assert.doesNotThrow(function() {
server = tls.createServer(soptions, function(cleartextStream) {
nconns++;
});
}, /SSLv2 Disabled/);
}
test1();
function test1() {
// Client has the preference of cipher suites by default
test(false, 'DES-CBC-SHA:RC4-SHA:AES256-SHA','DES-CBC-SHA');
}

55
test/simple/test-tls-enable-ssl3.js

@ -1,55 +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.
// Flags: --enable-ssl3
var common = require('../common');
var assert = require('assert');
var tls = require('tls');
var fs = require('fs');
var SSL_Method = 'SSLv3_method';
var localhost = '127.0.0.1';
function test(honorCipherOrder, clientCipher, expectedCipher, cb) {
var soptions = {
secureProtocol: SSL_Method,
key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'),
ciphers: 'AES256-SHA:RC4-SHA:DES-CBC-SHA',
honorCipherOrder: !!honorCipherOrder
};
var server;
assert.doesNotThrow(function() {
server = tls.createServer(soptions, function(cleartextStream) {
nconns++;
});
}, /SSLv3 Disabled/);
}
test1();
function test1() {
// Client has the preference of cipher suites by default
test(false, 'DES-CBC-SHA:RC4-SHA:AES256-SHA','DES-CBC-SHA');
}
Loading…
Cancel
Save