diff --git a/Changes.md b/Changes.md index a0ea3528a..077764d2d 100644 --- a/Changes.md +++ b/Changes.md @@ -6,6 +6,7 @@ you spot any mistakes. ## HEAD +* Accept the `maxVersion` and `minVersion` properties in connection `ssl` option #2301 #2304 * Support Node.js 14.x * Support Node.js 15.x * Support Node.js 16.x diff --git a/Readme.md b/Readme.md index 4726bc154..c83c14766 100644 --- a/Readme.md +++ b/Readme.md @@ -280,6 +280,10 @@ following options: * `ciphers`: The ciphers to use to use in the SSL handshake instead of the default ones for Node.js. This is passed as the `ciphers` option for [`tls.createSecureContext()`] call (or underlying [`crypto.createCredentials()`] if using Node.js below 0.12). +* `maxVersion`: This is passed as the `maxVersion` option for the underlying [`tls.createSecureContext()`] + call. +* `minVersion`: This is passed as the `minVersion` option for the underlying [`tls.createSecureContext()`] + call. * `key`: This is passed as the `key` option for [`tls.createSecureContext()`] call (or underlying [`crypto.createCredentials()`] if using Node.js below 0.12). * `passphrase`: This is passed as the `passphrase` option for [`tls.createSecureContext()`] call (or diff --git a/lib/Connection.js b/lib/Connection.js index 6802255dd..76fcbb049 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -306,7 +306,7 @@ if (tls.TLSSocket) { }); // cleartext <-> protocol - secureSocket.pipe(connection._protocol); + secureSocket.pipe(connection._protocol, { end: false }); connection._protocol.on('data', function(data) { secureSocket.write(data); }); @@ -465,6 +465,8 @@ function createSecureContext (config, cb) { cert : config.ssl.cert, ciphers : config.ssl.ciphers, key : config.ssl.key, + maxVersion : config.ssl.maxVersion, + minVersion : config.ssl.minVersion, passphrase : config.ssl.passphrase }); } catch (err) { diff --git a/test/unit/connection/test-connection-ssl-max-version-accept.js b/test/unit/connection/test-connection-ssl-max-version-accept.js new file mode 100644 index 000000000..f2e7419f1 --- /dev/null +++ b/test/unit/connection/test-connection-ssl-max-version-accept.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var common = require('../../common'); +var tls = require('tls'); + +if (!tls.createSecureContext) { + common.skipTest('node ' + process.version + ' does not support tls.createSecureContext()'); +} + +if (!tls.DEFAULT_MAX_VERSION) { + common.skipTest('node ' + process.version + ' does not support tls maxVersion'); +} + +var server = common.createFakeServer({ + ssl: { + maxVersion : tls.DEFAULT_MAX_VERSION, + minVersion : tls.DEFAULT_MAX_VERSION + } +}); + +server.listen(0, function (err) { + assert.ifError(err); + + var connection = common.createConnection({ + port : server.port(), + ssl : { + ca : common.getSSLConfig().ca, + maxVersion : tls.DEFAULT_MAX_VERSION + } + }); + + connection.connect(function (err) { + assert.ifError(err); + connection.destroy(); + server.destroy(); + }); +}); + +server.on('connection', function (incomingConnection) { + incomingConnection.handshake({ + serverCapabilities1: common.ClientConstants.CLIENT_SSL + }); +}); diff --git a/test/unit/connection/test-connection-ssl-max-version-reject.js b/test/unit/connection/test-connection-ssl-max-version-reject.js new file mode 100644 index 000000000..3660fa847 --- /dev/null +++ b/test/unit/connection/test-connection-ssl-max-version-reject.js @@ -0,0 +1,44 @@ +var assert = require('assert'); +var common = require('../../common'); +var tls = require('tls'); + +if (!tls.createSecureContext) { + common.skipTest('node ' + process.version + ' does not support tls.createSecureContext()'); +} + +if (!tls.DEFAULT_MAX_VERSION) { + common.skipTest('node ' + process.version + ' does not support tls maxVersion'); +} + +var server = common.createFakeServer({ + ssl: { + maxVersion : tls.DEFAULT_MAX_VERSION, + minVersion : tls.DEFAULT_MAX_VERSION + } +}); + +server.listen(0, function (err) { + assert.ifError(err); + + var connection = common.createConnection({ + port : server.port(), + ssl : { + ca : common.getSSLConfig().ca, + maxVersion : tls.DEFAULT_MIN_VERSION + } + }); + + connection.connect(function (err) { + assert.ok(err); + assert.strictEqual(err.code, 'HANDSHAKE_SSL_ERROR'); + assert.strictEqual(err.fatal, true); + connection.destroy(); + server.destroy(); + }); +}); + +server.on('connection', function (incomingConnection) { + incomingConnection.handshake({ + serverCapabilities1: common.ClientConstants.CLIENT_SSL + }); +}); diff --git a/test/unit/connection/test-connection-ssl-min-version-accept.js b/test/unit/connection/test-connection-ssl-min-version-accept.js new file mode 100644 index 000000000..a7e06fbe7 --- /dev/null +++ b/test/unit/connection/test-connection-ssl-min-version-accept.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var common = require('../../common'); +var tls = require('tls'); + +if (!tls.createSecureContext) { + common.skipTest('node ' + process.version + ' does not support tls.createSecureContext()'); +} + +if (!tls.DEFAULT_MIN_VERSION) { + common.skipTest('node ' + process.version + ' does not support tls minVersion'); +} + +var server = common.createFakeServer({ + ssl: { + maxVersion : tls.DEFAULT_MIN_VERSION, + minVersion : tls.DEFAULT_MIN_VERSION + } +}); + +server.listen(0, function (err) { + assert.ifError(err); + + var connection = common.createConnection({ + port : server.port(), + ssl : { + ca : common.getSSLConfig().ca, + minVersion : tls.DEFAULT_MIN_VERSION + } + }); + + connection.connect(function (err) { + assert.ifError(err); + connection.destroy(); + server.destroy(); + }); +}); + +server.on('connection', function (incomingConnection) { + incomingConnection.handshake({ + serverCapabilities1: common.ClientConstants.CLIENT_SSL + }); +}); diff --git a/test/unit/connection/test-connection-ssl-min-version-reject.js b/test/unit/connection/test-connection-ssl-min-version-reject.js new file mode 100644 index 000000000..ea88fe3be --- /dev/null +++ b/test/unit/connection/test-connection-ssl-min-version-reject.js @@ -0,0 +1,44 @@ +var assert = require('assert'); +var common = require('../../common'); +var tls = require('tls'); + +if (!tls.createSecureContext) { + common.skipTest('node ' + process.version + ' does not support tls.createSecureContext()'); +} + +if (!tls.DEFAULT_MIN_VERSION) { + common.skipTest('node ' + process.version + ' does not support tls minVersion'); +} + +var server = common.createFakeServer({ + ssl: { + maxVersion : tls.DEFAULT_MIN_VERSION, + minVersion : tls.DEFAULT_MIN_VERSION + } +}); + +server.listen(0, function (err) { + assert.ifError(err); + + var connection = common.createConnection({ + port : server.port(), + ssl : { + ca : common.getSSLConfig().ca, + minVersion : tls.DEFAULT_MAX_VERSION + } + }); + + connection.connect(function (err) { + assert.ok(err); + assert.strictEqual(err.code, 'HANDSHAKE_SSL_ERROR'); + assert.strictEqual(err.fatal, true); + connection.destroy(); + server.destroy(); + }); +}); + +server.on('connection', function (incomingConnection) { + incomingConnection.handshake({ + serverCapabilities1: common.ClientConstants.CLIENT_SSL + }); +});