Browse Source

Merge branch 'v0.10.33-release' into v0.10

v0.10.34-release
Timothy J Fontaine 10 years ago
parent
commit
e59eca58ad
  1. 3
      AUTHORS
  2. 23
      ChangeLog
  3. 44
      lib/crypto.js
  4. 19
      lib/tls.js
  5. 2
      src/node_version.h
  6. 1
      test/external/ssl-options/.gitignore
  7. 15
      test/external/ssl-options/package.json
  8. 729
      test/external/ssl-options/test.js
  9. 131
      test/simple/test-tls-honorcipherorder-secureOptions.js

3
AUTHORS

@ -515,3 +515,6 @@ Kevin Simper <kevin.simper@gmail.com>
Jackson Tian <shyvo1987@gmail.com>
Tristan Berger <tristan.berger@gmail.com>
Mathias Schreck <schreck.mathias@googlemail.com>
Calvin Metcalf <cmetcalf@appgeo.com>
Matthew Fitzsimmons <matt@fitzage.com>
Swaagie <info@martijnswaagman.nl>

23
ChangeLog

@ -1,4 +1,25 @@
2014.09.16, Version 0.10.32 (Stable)
2014.10.20, Version 0.10.33 (Stable)
* openssl: Update to 1.0.1j (Addressing multiple CVEs)
* uv: Update to v0.10.29
* child_process: properly support optional args (cjihrig)
* crypto: Disable autonegotiation for SSLv2/3 by default (Fedor Indutny,
Timothy J Fontaine, Alexis Campailla)
This is a behavior change, by default we will not allow the negotiation to
SSLv2 or SSLv3. If you want this behavior, run Node.js with either
`--enable-ssl2` or `--enable-ssl3` respectively.
This does not change the behavior for users specifically requesting
`SSLv2_method` or `SSLv3_method`. While this behavior is not advised, it is
assumed you know what you're doing since you're specifically asking to use
these methods.
2014.09.16, Version 0.10.32 (Stable), 0fe0d121551593c23a565db8397f85f17bb0f00e
* npm: Update to 1.4.28

44
lib/crypto.js

@ -61,6 +61,31 @@ var StringDecoder = require('string_decoder').StringDecoder;
var CONTEXT_DEFAULT_OPTIONS = undefined;
function getSecureOptions(secureProtocol, secureOptions) {
if (CONTEXT_DEFAULT_OPTIONS === undefined) {
CONTEXT_DEFAULT_OPTIONS = 0;
if (!binding.SSL3_ENABLE)
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv3;
if (!binding.SSL2_ENABLE)
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv2;
}
if (secureOptions === undefined) {
if (secureProtocol === undefined ||
secureProtocol === 'SSLv23_method' ||
secureProtocol === 'SSLv23_server_method' ||
secureProtocol === 'SSLv23_client_method') {
secureOptions |= CONTEXT_DEFAULT_OPTIONS;
}
}
return secureOptions;
}
exports._getSecureOptions = getSecureOptions;
function Credentials(secureProtocol, flags, context) {
if (!(this instanceof Credentials)) {
return new Credentials(secureProtocol, flags, context);
@ -82,24 +107,7 @@ function Credentials(secureProtocol, flags, context) {
}
}
if (CONTEXT_DEFAULT_OPTIONS === undefined) {
CONTEXT_DEFAULT_OPTIONS = 0;
if (!binding.SSL3_ENABLE)
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv3;
if (!binding.SSL2_ENABLE)
CONTEXT_DEFAULT_OPTIONS |= constants.SSL_OP_NO_SSLv2;
}
if (flags === undefined) {
if (secureProtocol === undefined ||
secureProtocol === 'SSLv23_method' ||
secureProtocol === 'SSLv23_server_method' ||
secureProtocol === 'SSLv23_client_method') {
flags |= CONTEXT_DEFAULT_OPTIONS;
}
}
flags = getSecureOptions(secureProtocol, flags);
this.context.setOptions(flags);
}

19
lib/tls.js

@ -1145,7 +1145,12 @@ function Server(/* [options], listener */) {
// constructor call
net.Server.call(this, function(socket) {
var creds = crypto.createCredentials(null, sharedCreds.context);
var connOps = {
secureProtocol: self.secureProtocol,
secureOptions: self.secureOptions
};
var creds = crypto.createCredentials(connOps, sharedCreds.context);
var pair = new SecurePair(creds,
true,
@ -1239,11 +1244,16 @@ Server.prototype.setOptions = function(options) {
if (options.secureProtocol) this.secureProtocol = options.secureProtocol;
if (options.crl) this.crl = options.crl;
if (options.ciphers) this.ciphers = options.ciphers;
var secureOptions = options.secureOptions || 0;
var secureOptions = crypto._getSecureOptions(options.secureProtocol,
options.secureOptions);
if (options.honorCipherOrder) {
secureOptions |= constants.SSL_OP_CIPHER_SERVER_PREFERENCE;
}
if (secureOptions) this.secureOptions = secureOptions;
this.secureOptions = secureOptions;
if (options.NPNProtocols) convertNPNProtocols(options.NPNProtocols, this);
if (options.SNICallback) {
this.SNICallback = options.SNICallback;
@ -1326,6 +1336,9 @@ exports.connect = function(/* [port, host], options, cb */) {
};
options = util._extend(defaults, options || {});
options.secureOptions = crypto._getSecureOptions(options.secureProtocol,
options.secureOptions);
var socket = options.socket ? options.socket : new net.Stream();
var sslcontext = crypto.createCredentials(options);

2
src/node_version.h

@ -26,7 +26,7 @@
#define NODE_MINOR_VERSION 10
#define NODE_PATCH_VERSION 33
#define NODE_VERSION_IS_RELEASE 0
#define NODE_VERSION_IS_RELEASE 1
#ifndef NODE_TAG
# define NODE_TAG ""

1
test/external/ssl-options/.gitignore

@ -0,0 +1 @@
node_modules/

15
test/external/ssl-options/package.json

@ -0,0 +1,15 @@
{
"name": "ssl-options-tests",
"version": "1.0.0",
"description": "",
"main": "test.js",
"scripts": {
"test": "node test.js"
},
"author": "",
"license": "MIT",
"dependencies": {
"async": "^0.9.0",
"debug": "^2.1.0"
}
}

729
test/external/ssl-options/test.js

@ -0,0 +1,729 @@
var tls = require('tls');
var fs = require('fs');
var path = require('path');
var fork = require('child_process').fork;
var assert = require('assert');
var constants = require('constants');
var os = require('os');
var async = require('async');
var debug = require('debug')('test-node-ssl');
var common = require('../../common');
var SSL2_COMPATIBLE_CIPHERS = 'RC4-MD5';
var CMD_LINE_OPTIONS = [ null, "--enable-ssl2", "--enable-ssl3" ];
var SERVER_SSL_PROTOCOLS = [
null,
'SSLv2_method', 'SSLv2_server_method',
'SSLv3_method', 'SSLv3_server_method',
'TLSv1_method', 'TLSv1_server_method',
'SSLv23_method','SSLv23_server_method'
];
var CLIENT_SSL_PROTOCOLS = [
null,
'SSLv2_method', 'SSLv2_client_method',
'SSLv3_method', 'SSLv3_client_method',
'TLSv1_method', 'TLSv1_client_method',
'SSLv23_method','SSLv23_client_method'
];
var SECURE_OPTIONS = [
null,
0,
constants.SSL_OP_NO_SSLv2,
constants.SSL_OP_NO_SSLv3,
constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3
];
function xtend(source) {
var clone = {};
for (var property in source) {
if (source.hasOwnProperty(property)) {
clone[property] = source[property];
}
}
return clone;
}
function isAutoNegotiationProtocol(sslProtocol) {
assert(sslProtocol === null || typeof sslProtocol === 'string');
return sslProtocol == null ||
sslProtocol === 'SSLv23_method' ||
sslProtocol === 'SSLv23_client_method' ||
sslProtocol === 'SSLv23_server_method';
}
function isSameSslProtocolVersion(serverSecureProtocol, clientSecureProtocol) {
assert(serverSecureProtocol === null || typeof serverSecureProtocol === 'string');
assert(clientSecureProtocol === null || typeof clientSecureProtocol === 'string');
if (serverSecureProtocol === clientSecureProtocol) {
return true;
}
var serverProtocolPrefix = '';
if (serverSecureProtocol)
serverProtocolPrefix = serverSecureProtocol.split('_')[0];
var clientProtocolPrefix = '';
if (clientSecureProtocol)
clientProtocolPrefix = clientSecureProtocol.split('_')[0];
if (serverProtocolPrefix === clientProtocolPrefix) {
return true;
}
return false;
}
function secureProtocolsCompatible(serverSecureProtocol, clientSecureProtocol) {
if (isAutoNegotiationProtocol(serverSecureProtocol) ||
isAutoNegotiationProtocol(clientSecureProtocol)) {
return true;
}
if (isSameSslProtocolVersion(serverSecureProtocol,
clientSecureProtocol)) {
return true;
}
return false;
}
function isSsl3Protocol(secureProtocol) {
assert(secureProtocol === null || typeof secureProtocol === 'string');
return secureProtocol === 'SSLv3_method' ||
secureProtocol === 'SSLv3_client_method' ||
secureProtocol === 'SSLv3_server_method';
}
function isSsl2Protocol(secureProtocol) {
assert(secureProtocol === null || typeof secureProtocol === 'string');
return secureProtocol === 'SSLv2_method' ||
secureProtocol === 'SSLv2_client_method' ||
secureProtocol === 'SSLv2_server_method';
}
function secureProtocolCompatibleWithSecureOptions(secureProtocol, secureOptions, cmdLineOption) {
if (secureOptions == null) {
if (isSsl2Protocol(secureProtocol) &&
(!cmdLineOption || cmdLineOption.indexOf('--enable-ssl2') === -1)) {
return false;
}
if (isSsl3Protocol(secureProtocol) &&
(!cmdLineOption || cmdLineOption.indexOf('--enable-ssl3') === -1)) {
return false;
}
} else {
if (secureOptions & constants.SSL_OP_NO_SSLv2 && isSsl2Protocol(secureProtocol)) {
return false;
}
if (secureOptions & constants.SSL_OP_NO_SSLv3 && isSsl3Protocol(secureProtocol)) {
return false;
}
}
return true;
}
function testSetupsCompatible(serverSetup, clientSetup) {
debug('Determing test result for:');
debug(serverSetup);
debug(clientSetup);
/*
* If the protocols specified by the client and server are
* not compatible (e.g SSLv2 vs SSLv3), then the test should fail.
*/
if (!secureProtocolsCompatible(serverSetup.secureProtocol,
clientSetup.secureProtocol)) {
debug('secureProtocols not compatible! server secureProtocol: ' +
serverSetup.secureProtocol + ', client secureProtocol: ' +
clientSetup.secureProtocol);
return false;
}
/*
* If the client's options are not compatible with the server's protocol,
* then the test should fail. Same if server's options are not compatible
* with the client's protocol.
*/
if (!secureProtocolCompatibleWithSecureOptions(serverSetup.secureProtocol,
clientSetup.secureOptions,
clientSetup.cmdLine) ||
!secureProtocolCompatibleWithSecureOptions(clientSetup.secureProtocol,
serverSetup.secureOptions,
serverSetup.cmdLine)) {
debug('Secure protocol not compatible with secure options!');
return false;
}
if (isSsl2Protocol(serverSetup.secureProtocol) ||
isSsl2Protocol(clientSetup.secureProtocol)) {
/*
* It seems that in order to be able to use SSLv2, at least the server
* *needs* to advertise at least one cipher compatible with it.
*/
if (serverSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS) {
return false;
}
/*
* If only either one of the client or server specify SSLv2 as their
* protocol, then *both* of them *need* to advertise at least one cipher
* that is compatible with SSLv2.
*/
if ((!isSsl2Protocol(serverSetup.secureProtocol) || !isSsl2Protocol(clientSetup.secureProtocol)) &&
(clientSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS || serverSetup.ciphers !== SSL2_COMPATIBLE_CIPHERS)) {
return false;
}
}
return true;
}
function sslSetupMakesSense(cmdLineOption, secureProtocol, secureOption) {
if (isSsl2Protocol(secureProtocol)) {
if (secureOption & constants.SSL_OP_NO_SSLv2 ||
(secureOption == null && (!cmdLineOption || cmdLineOption.indexOf('--enable-ssl2') === -1))) {
return false;
}
}
if (isSsl3Protocol(secureProtocol)) {
if (secureOption & constants.SSL_OP_NO_SSLv3 ||
(secureOption == null && (!cmdLineOption || cmdLineOption.indexOf('--enable-ssl3') === -1))) {
return false;
}
}
return true;
}
function createTestsSetups() {
var serversSetup = [];
var clientsSetup = [];
CMD_LINE_OPTIONS.forEach(function (cmdLineOption) {
SERVER_SSL_PROTOCOLS.forEach(function (serverSecureProtocol) {
SECURE_OPTIONS.forEach(function (secureOption) {
if (sslSetupMakesSense(cmdLineOption,
serverSecureProtocol,
secureOption)) {
var serverSetup = {
cmdLine: cmdLineOption,
secureProtocol: serverSecureProtocol,
secureOptions: secureOption
};
serversSetup.push(serverSetup);
if (isSsl2Protocol(serverSecureProtocol)) {
var setupWithSsl2Ciphers = xtend(serverSetup);
setupWithSsl2Ciphers.ciphers = SSL2_COMPATIBLE_CIPHERS;
serversSetup.push(setupWithSsl2Ciphers);
}
}
});
});
CLIENT_SSL_PROTOCOLS.forEach(function (clientSecureProtocol) {
SECURE_OPTIONS.forEach(function (secureOption) {
if (sslSetupMakesSense(cmdLineOption,
clientSecureProtocol,
secureOption)) {
var clientSetup = {
cmdLine: cmdLineOption,
secureProtocol: clientSecureProtocol,
secureOptions: secureOption
};
clientsSetup.push(clientSetup);
if (isSsl2Protocol(clientSecureProtocol)) {
var setupWithSsl2Ciphers = xtend(clientSetup);
setupWithSsl2Ciphers.ciphers = SSL2_COMPATIBLE_CIPHERS;
clientsSetup.push(setupWithSsl2Ciphers);
}
}
});
});
});
var testSetups = [];
var testId = 0;
serversSetup.forEach(function (serverSetup) {
clientsSetup.forEach(function (clientSetup) {
var testSetup = {
server: serverSetup,
client: clientSetup,
ID: testId++
};
var successExpected = false;
if (testSetupsCompatible(serverSetup, clientSetup)) {
successExpected = true;
}
testSetup.successExpected = successExpected;
testSetups.push(testSetup);
});
});
return testSetups;
}
function runServer(port, secureProtocol, secureOptions, ciphers) {
debug('Running server!');
debug('port: ' + port);
debug('secureProtocol: ' + secureProtocol);
debug('secureOptions: ' + secureOptions);
debug('ciphers: ' + ciphers);
var keyPath = path.join(common.fixturesDir, 'agent.key');
var certPath = path.join(common.fixturesDir, 'agent.crt');
var key = fs.readFileSync(keyPath).toString();
var cert = fs.readFileSync(certPath).toString();
var server = new tls.Server({ key: key,
cert: cert,
ca: [],
ciphers: ciphers,
secureProtocol: secureProtocol,
secureOptions: secureOptions
});
server.listen(port, function() {
process.on('message', function onChildMsg(msg) {
if (msg === 'close') {
server.close();
process.exit(0);
}
});
process.send('server_listening');
});
server.on('error', function onServerError(err) {
debug('Server error: ' + err);
process.exit(1);
});
server.on('clientError', function onClientError(err) {
debug('Client error on server: ' + err);
process.exit(1);
});
}
function runClient(port, secureProtocol, secureOptions, ciphers) {
debug('Running client!');
debug('port: ' + port);
debug('secureProtocol: ' + secureProtocol);
debug('secureOptions: ' + secureOptions);
debug('ciphers: ' + ciphers);
var con = tls.connect(port,
{
rejectUnauthorized: false,
secureProtocol: secureProtocol,
secureOptions: secureOptions
},
function() {
// TODO jgilli: test that sslProtocolUsed is at least as "secure" as
// "secureProtocol"
/*
* var sslProtocolUsed = con.getVersion();
* debug('Protocol used: ' + sslProtocolUsed);
*/
process.send('client_done');
});
con.on('error', function(err) {
debug('Client could not connect:' + err);
process.exit(1);
});
}
function stringToSecureOptions(secureOptionsString) {
assert(typeof secureOptionsString === 'string');
var secureOptions;
var optionStrings = secureOptionsString.split('|');
optionStrings.forEach(function (option) {
if (option === 'SSL_OP_NO_SSLv2') {
secureOptions |= constants.SSL_OP_NO_SSLv2;
}
if (option === 'SSL_OP_NO_SSLv3') {
secureOptions |= constants.SSL_OP_NO_SSLv3;
}
if (option === '0') {
secureOptions = 0;
}
});
return secureOptions;
}
function processTestCmdLineOptions(argv){
var options = {};
argv.forEach(function (arg) {
var key;
var value;
var keyValue = arg.split(':');
var key = keyValue[0];
if (keyValue.length == 2 && keyValue[1].length > 0) {
value = keyValue[1];
if (key === 'secureOptions') {
value = stringToSecureOptions(value);
}
if (key === 'port') {
value = +value;
}
}
options[key] = value;
});
return options;
}
function checkTestExitCode(testSetup, serverExitCode, clientExitCode) {
if (testSetup.successExpected) {
if (serverExitCode === 0 && clientExitCode === 0) {
debug('Test succeeded as expected!');
return true;
}
} else {
if (serverExitCode !== 0 || clientExitCode !== 0) {
debug('Test failed as expected!');
return true;
}
}
return false;
}
function secureOptionsToString(secureOptions) {
var secureOptsString = '';
if (secureOptions & constants.SSL_OP_NO_SSLv2) {
secureOptsString += 'SSL_OP_NO_SSLv2';
}
if (secureOptions & constants.SSL_OP_NO_SSLv3) {
secureOptsString += '|SSL_OP_NO_SSLv3';
}
if (secureOptions === 0) {
secureOptsString = '0';
}
return secureOptsString;
}
function forkTestProcess(processType, testSetup, port) {
var argv = [ processType ];
if (testSetup.secureProtocol) {
argv.push('secureProtocol:' + testSetup.secureProtocol);
} else {
argv.push('secureProtocol:');
}
argv.push('secureOptions:' + secureOptionsToString(testSetup.secureOptions));
if (testSetup.ciphers) {
argv.push('ciphers:' + testSetup.ciphers);
} else {
argv.push('ciphers:');
}
argv.push('port:' + port);
var forkOptions;
if (testSetup.cmdLine) {
forkOptions = {
execArgv: [ testSetup.cmdLine ]
}
}
return fork(process.argv[1],
argv,
forkOptions);
}
function runTest(testSetup, testDone) {
var clientSetup = testSetup.client;
var serverSetup = testSetup.server;
assert(clientSetup);
assert(serverSetup);
debug('Starting new test on port: ' + testSetup.port);
debug('client setup:');
debug(clientSetup);
debug('server setup:');
debug(serverSetup);
debug('Success expected:' + testSetup.successExpected);
var serverExitCode;
var clientStarted = false;
var clientExitCode;
var serverChild = forkTestProcess('server', serverSetup, testSetup.port);
assert(serverChild);
serverChild.on('message', function onServerMsg(msg) {
if (msg === 'server_listening') {
debug('Starting client!');
clientStarted = true;
var clientChild = forkTestProcess('client', clientSetup, testSetup.port);
assert(clientChild);
clientChild.on('exit', function onClientExited(exitCode) {
debug('Client exited with code:' + exitCode);
clientExitCode = exitCode;
if (serverExitCode != null) {
var err;
if (!checkTestExitCode(testSetup, serverExitCode, clientExitCode))
err = new Error("Test failed!");
return testDone(err);
} else {
if (serverChild.connected) {
serverChild.send('close');
}
}
});
clientChild.on('message', function onClientMsg(msg) {
if (msg === 'client_done' && serverChild.connected) {
serverChild.send('close');
}
})
}
});
serverChild.on('exit', function onServerExited(exitCode) {
debug('Server exited with code:' + exitCode);
serverExitCode = exitCode;
if (clientExitCode != null || !clientStarted) {
var err;
if (!checkTestExitCode(testSetup, serverExitCode, clientExitCode))
err = new Error("Test failed!");
return testDone(err);
}
});
}
function usage() {
console.log('Usage: test-node-ssl [-j N] [--list-tests] [-s startIndex] ' +
'[-e endIndex] [-o outputFile]');
process.exit(1);
}
function processDriverCmdLineOptions(argv) {
var options = {
parallelTests: 1
};
for (var i = 1; i < argv.length; ++i) {
if (argv[i] === '-j') {
var nbParallelTests = +argv[i + 1];
if (!nbParallelTests) {
usage();
} else {
options.parallelTests = argv[++i];
}
}
if (argv[i] === '-s') {
var start = +argv[i + 1];
if (!start) {
usage();
} else {
options.start = argv[++i];
}
}
if (argv[i] === '-e') {
var end = +argv[i + 1];
if (!end) {
usage();
} else {
options.end = argv[++i];
}
}
if (argv[i] === '--list-tests') {
options.listTests = true;
}
if (argv[i] === '-o') {
var outputFile = argv[i + 1];
if (!outputFile) {
usage();
} else {
options.outputFile = argv[++i];
}
}
}
return options;
}
function outputTestResult(test, err, output) {
output.write(os.EOL);
output.write('Test:' + os.EOL);
output.write(JSON.stringify(test, null, " "));
output.write(os.EOL);
output.write('Result:');
output.write(err ? 'failure' : 'success');
output.write(os.EOL);
}
var agentType = process.argv[2];
if (agentType === 'client' || agentType === 'server') {
var options = processTestCmdLineOptions(process.argv);
debug('secureProtocol: ' + options.secureProtocol);
debug('secureOptions: ' + options.secureOptions);
debug('ciphers:' + options.ciphers);
debug('port:' + options.port);
if (agentType === 'client') {
runClient(options.port,
options.secureProtocol,
options.secureOptions,
options.ciphers);
} else if (agentType === 'server') {
runServer(options.port,
options.secureProtocol,
options.secureOptions,
options.ciphers);
}
} else {
var driverOptions = processDriverCmdLineOptions(process.argv);
debug('Tests driver options:');
debug(driverOptions);
/*
* This is the tests driver process.
*
* It forks itself twice for each test. Each of the two forked processees are
* respectfully used as an SSL client and an SSL server. The client and
* server setup their SSL connection as generated by the "createTestsSetups"
* function. Once both processes have exited, the tests driver process
* compare both client and server exit codes with the expected test result
* of the test setup. If they match, the test is successful, otherwise it
* failed.
*/
var testSetups = createTestsSetups();
if (driverOptions.listTests) {
console.log(testSetups);
process.exit(0);
}
var testOutput = process.stdout;
if (driverOptions.outputFile) {
testOutput = fs.createWriteStream(driverOptions.outputFile)
.on('error', function onError(err) {
console.error(err);
process.exit(1);
});
}
debug('Tests setups:');
debug('Number of tests: ' + testSetups.length);
debug(JSON.stringify(testSetups, null, " "));
debug();
var nbTestsStarted = 0;
function runTests(tests, callback) {
var nbTests = tests.length;
if (nbTests === 0) {
return callback();
}
var error;
var nbTestsDone = 0;
debug('Starting new batch of tests...');
var port = common.PORT;
async.each(tests, function (test, testDone) {
test.port = port++;
++nbTestsStarted;
debug('Starting test nb: ' + nbTestsStarted);
runTest(test, function onTestDone(err) {
++nbTestsDone;
if (err && error === undefined) {
error = new Error('Test with ID ' + test.ID + ' failed: ' + err);
}
outputTestResult(test, err, testOutput);
if (nbTestsDone === nbTests)
return testDone(error);
return testDone();
});
}, function testsDone(err, results) {
if (err) {
assert(false,
"At least one test in the most recent batch failed: " + err);
}
return callback(err);
});
}
function runAllTests(allTests, allTestsDone) {
if (allTests.length === 0) {
return allTestsDone();
}
return runTests(allTests.splice(0, driverOptions.parallelTests),
runAllTests.bind(global, allTests, allTestsDone));
}
runAllTests(testSetups.slice(driverOptions.start, driverOptions.end),
function allDone(err) {
console.log('All tests done!');
});
}

131
test/simple/test-tls-honorcipherorder-secureOptions.js

@ -0,0 +1,131 @@
// 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 nconns = 0;
var SSL_Method = 'SSLv23_method';
var localhost = '127.0.0.1';
var opCipher = process.binding('constants').SSL_OP_CIPHER_SERVER_PREFERENCE;
/*
* This test is to make sure we are preserving secureOptions that are passed
* to the server.
*
* Also that if honorCipherOrder is passed we are preserving that in the
* options.
*
* And that if we are passing in secureOptions no new options (aside from the
* honorCipherOrder case) are added to the secureOptions
*/
process.on('exit', function() {
assert.equal(nconns, 6);
});
function test(honorCipherOrder, clientCipher, expectedCipher, secureOptions, 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',
secureOptions: secureOptions,
honorCipherOrder: !!honorCipherOrder
};
var server = tls.createServer(soptions, function(cleartextStream) {
nconns++;
});
if (!!honorCipherOrder) {
assert.strictEqual(server.secureOptions & opCipher, opCipher, 'we should preserve cipher preference');
}
if (secureOptions) {
var expectedSecureOpts = secureOptions;
if (!!honorCipherOrder) expectedSecureOpts |= opCipher;
assert.strictEqual(server.secureOptions & expectedSecureOpts,
expectedSecureOpts, 'we should preserve secureOptions');
assert.strictEqual(server.secureOptions & ~expectedSecureOpts,
0,
'we should not add extra options');
}
server.listen(common.PORT, localhost, function() {
var coptions = {
rejectUnauthorized: false,
secureProtocol: SSL_Method
};
if (clientCipher) {
coptions.ciphers = clientCipher;
}
var client = tls.connect(common.PORT, localhost, coptions, function() {
var cipher = client.getCipher();
client.end();
server.close();
assert.equal(cipher.name, expectedCipher);
if (cb) cb();
});
});
}
test1();
function test1() {
// Client has the preference of cipher suites by default
test(false, 'DES-CBC-SHA:RC4-SHA:AES256-SHA','DES-CBC-SHA', 0, test2);
}
function test2() {
// Server has the preference of cipher suites where AES256-SHA is in
// the first.
test(true, 'DES-CBC-SHA:RC4-SHA:AES256-SHA', 'AES256-SHA', 0, test3);
}
function test3() {
// Server has the preference of cipher suites. RC4-SHA is given
// higher priority over DES-CBC-SHA among client cipher suites.
test(true, 'DES-CBC-SHA:RC4-SHA', 'RC4-SHA', 0, test4);
}
function test4() {
// As client has only one cipher, server has no choice in regardless
// of honorCipherOrder.
test(true, 'DES-CBC-SHA', 'DES-CBC-SHA', 0, test5);
}
function test5() {
test(false,
'DES-CBC-SHA',
'DES-CBC-SHA',
process.binding('constants').SSL_OP_SINGLE_DH_USE, test6);
}
function test6() {
test(true,
'DES-CBC-SHA',
'DES-CBC-SHA',
process.binding('constants').SSL_OP_SINGLE_DH_USE);
}
Loading…
Cancel
Save