tls: add min/max protocol version options

The existing secureProtocol option only allows setting the allowed
protocol to a specific version, or setting it to "all supported
versions". It also used obscure strings based on OpenSSL C API
functions. Directly setting the min or max is easier to use and explain.

PR-URL: https://github.com/nodejs/node/pull/24405
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Rod Vagg <rod@vagg.org>
This commit is contained in:
Sam Roberts 2018-05-06 13:52:34 +09:00
parent 160ac0f325
commit f512f5ea13
14 changed files with 327 additions and 45 deletions

View File

@ -1655,6 +1655,17 @@ recommended to use 2048 bits or larger for stronger security.
A TLS/SSL handshake timed out. In this case, the server must also abort the A TLS/SSL handshake timed out. In this case, the server must also abort the
connection. connection.
<a id="ERR_TLS_INVALID_PROTOCOL_VERSION"></a>
### ERR_TLS_INVALID_PROTOCOL_VERSION
Valid TLS protocol versions are `'TLSv1'`, `'TLSv1.1'`, or `'TLSv1.2'`.
<a id="ERR_TLS_PROTOCOL_VERSION_CONFLICT"></a>
### ERR_TLS_PROTOCOL_VERSION_CONFLICT
Attempting to set a TLS protocol `minVersion` or `maxVersion` conflicts with an
attempt to set the `secureProtocol` explicitly. Use one mechanism or the other.
<a id="ERR_TLS_RENEGOTIATE"></a> <a id="ERR_TLS_RENEGOTIATE"></a>
### ERR_TLS_RENEGOTIATE ### ERR_TLS_RENEGOTIATE

View File

@ -1070,6 +1070,10 @@ changes:
pr-url: https://github.com/nodejs/node/pull/4099 pr-url: https://github.com/nodejs/node/pull/4099
description: The `ca` option can now be a single string containing multiple description: The `ca` option can now be a single string containing multiple
CA certificates. CA certificates.
- version: REPLACEME
pr-url: REPLACEME
description: The `minVersion` and `maxVersion` can be used to restrict
the allowed TLS protocol versions.
--> -->
* `options` {Object} * `options` {Object}
@ -1130,6 +1134,16 @@ changes:
passphrase: <string>]}`. The object form can only occur in an array. passphrase: <string>]}`. The object form can only occur in an array.
`object.passphrase` is optional. Encrypted keys will be decrypted with `object.passphrase` is optional. Encrypted keys will be decrypted with
`object.passphrase` if provided, or `options.passphrase` if it is not. `object.passphrase` if provided, or `options.passphrase` if it is not.
* `maxVersion` {string} Optionally set the maximum TLS version to allow. One
of `TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified along with the
`secureProtocol` option, use one or the other. **Default:** `'TLSv1.2'`.
* `minVersion` {string} Optionally set the minimum TLS version to allow. One
of `TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified along with the
`secureProtocol` option, use one or the other. It is not recommended to use
less than TLSv1.2, but it may be required for interoperability.
**Default:** `'TLSv1.2'`, unless changed using CLI options. Using
`--tls-v1.0` changes the default to `'TLSv1'`. Using `--tls-v1.1` changes
the default to `'TLSv1.1'`.
* `passphrase` {string} Shared passphrase used for a single private key and/or * `passphrase` {string} Shared passphrase used for a single private key and/or
a PFX. a PFX.
* `pfx` {string|string[]|Buffer|Buffer[]|Object[]} PFX or PKCS12 encoded * `pfx` {string|string[]|Buffer|Buffer[]|Object[]} PFX or PKCS12 encoded
@ -1150,10 +1164,7 @@ changes:
example, use `'TLSv1_1_method'` to force TLS version 1.1, or `'TLS_method'` example, use `'TLSv1_1_method'` to force TLS version 1.1, or `'TLS_method'`
to allow any TLS protocol version. It is not recommended to use TLS versions to allow any TLS protocol version. It is not recommended to use TLS versions
less than 1.2, but it may be required for interoperability. **Default:** less than 1.2, but it may be required for interoperability. **Default:**
`'TLSv1_2_method'`, unless changed using CLI options. Using the `--tlsv1.0` none, see `minVersion`.
CLI option is like `'TLS_method'` except protocols earlier than TLSv1.0 are
not allowed, and using the `--tlsv1.1` CLI option is like `'TLS_method'`
except that protocols earlier than TLSv1.1 are not allowed.
* `sessionIdContext` {string} Opaque identifier used by servers to ensure * `sessionIdContext` {string} Opaque identifier used by servers to ensure
session state is not shared between applications. Unused by clients. session state is not shared between applications. Unused by clients.

View File

@ -26,22 +26,46 @@ const { isArrayBufferView } = require('internal/util/types');
const tls = require('tls'); const tls = require('tls');
const { const {
ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED, ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED,
ERR_INVALID_ARG_TYPE ERR_INVALID_ARG_TYPE,
ERR_TLS_INVALID_PROTOCOL_VERSION,
ERR_TLS_PROTOCOL_VERSION_CONFLICT,
} = require('internal/errors').codes; } = require('internal/errors').codes;
const {
const { SSL_OP_CIPHER_SERVER_PREFERENCE } = internalBinding('constants').crypto; SSL_OP_CIPHER_SERVER_PREFERENCE,
TLS1_VERSION,
TLS1_1_VERSION,
TLS1_2_VERSION,
} = internalBinding('constants').crypto;
// Lazily loaded from internal/crypto/util. // Lazily loaded from internal/crypto/util.
let toBuf = null; let toBuf = null;
function toV(which, v, def) {
if (v == null) v = def;
if (v === 'TLSv1') return TLS1_VERSION;
if (v === 'TLSv1.1') return TLS1_1_VERSION;
if (v === 'TLSv1.2') return TLS1_2_VERSION;
throw new ERR_TLS_INVALID_PROTOCOL_VERSION(v, which);
}
const { SecureContext: NativeSecureContext } = internalBinding('crypto'); const { SecureContext: NativeSecureContext } = internalBinding('crypto');
function SecureContext(secureProtocol, secureOptions) { function SecureContext(secureProtocol, secureOptions, minVersion, maxVersion) {
if (!(this instanceof SecureContext)) { if (!(this instanceof SecureContext)) {
return new SecureContext(secureProtocol, secureOptions); return new SecureContext(secureProtocol, secureOptions, minVersion,
maxVersion);
}
if (secureProtocol) {
if (minVersion != null)
throw new ERR_TLS_PROTOCOL_VERSION_CONFLICT(minVersion, secureProtocol);
if (maxVersion != null)
throw new ERR_TLS_PROTOCOL_VERSION_CONFLICT(maxVersion, secureProtocol);
} }
this.context = new NativeSecureContext(); this.context = new NativeSecureContext();
this.context.init(secureProtocol); this.context.init(secureProtocol,
toV('minimum', minVersion, tls.DEFAULT_MIN_VERSION),
toV('maximum', maxVersion, tls.DEFAULT_MAX_VERSION));
if (secureOptions) this.context.setOptions(secureOptions); if (secureOptions) this.context.setOptions(secureOptions);
} }
@ -66,7 +90,8 @@ exports.createSecureContext = function createSecureContext(options) {
if (options.honorCipherOrder) if (options.honorCipherOrder)
secureOptions |= SSL_OP_CIPHER_SERVER_PREFERENCE; secureOptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
const c = new SecureContext(options.secureProtocol, secureOptions); const c = new SecureContext(options.secureProtocol, secureOptions,
options.minVersion, options.maxVersion);
var i; var i;
var val; var val;

View File

@ -918,6 +918,16 @@ Server.prototype.setSecureContext = function(options) {
else else
this.ca = undefined; this.ca = undefined;
if (options.minVersion)
this.minVersion = options.minVersion;
else
this.minVersion = undefined;
if (options.maxVersion)
this.maxVersion = options.maxVersion;
else
this.maxVersion = undefined;
if (options.secureProtocol) if (options.secureProtocol)
this.secureProtocol = options.secureProtocol; this.secureProtocol = options.secureProtocol;
else else
@ -974,6 +984,8 @@ Server.prototype.setSecureContext = function(options) {
ciphers: this.ciphers, ciphers: this.ciphers,
ecdhCurve: this.ecdhCurve, ecdhCurve: this.ecdhCurve,
dhparam: this.dhparam, dhparam: this.dhparam,
minVersion: this.minVersion,
maxVersion: this.maxVersion,
secureProtocol: this.secureProtocol, secureProtocol: this.secureProtocol,
secureOptions: this.secureOptions, secureOptions: this.secureOptions,
honorCipherOrder: this.honorCipherOrder, honorCipherOrder: this.honorCipherOrder,
@ -1026,6 +1038,8 @@ Server.prototype.setOptions = util.deprecate(function(options) {
if (options.clientCertEngine) if (options.clientCertEngine)
this.clientCertEngine = options.clientCertEngine; this.clientCertEngine = options.clientCertEngine;
if (options.ca) this.ca = options.ca; if (options.ca) this.ca = options.ca;
if (options.minVersion) this.minVersion = options.minVersion;
if (options.maxVersion) this.maxVersion = options.maxVersion;
if (options.secureProtocol) this.secureProtocol = options.secureProtocol; if (options.secureProtocol) this.secureProtocol = options.secureProtocol;
if (options.crl) this.crl = options.crl; if (options.crl) this.crl = options.crl;
if (options.ciphers) this.ciphers = options.ciphers; if (options.ciphers) this.ciphers = options.ciphers;

View File

@ -186,6 +186,14 @@ Agent.prototype.getName = function getName(options) {
if (options.servername && options.servername !== options.host) if (options.servername && options.servername !== options.host)
name += options.servername; name += options.servername;
name += ':';
if (options.minVersion)
name += options.minVersion;
name += ':';
if (options.maxVersion)
name += options.maxVersion;
name += ':'; name += ':';
if (options.secureProtocol) if (options.secureProtocol)
name += options.secureProtocol; name += options.secureProtocol;

View File

@ -861,6 +861,10 @@ E('ERR_TLS_CERT_ALTNAME_INVALID',
'Hostname/IP does not match certificate\'s altnames: %s', Error); 'Hostname/IP does not match certificate\'s altnames: %s', Error);
E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error); E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error);
E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout', Error); E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout', Error);
E('ERR_TLS_INVALID_PROTOCOL_VERSION',
'%j is not a valid %s TLS protocol version', TypeError);
E('ERR_TLS_PROTOCOL_VERSION_CONFLICT',
'TLS protocol version %j conflicts with secureProtocol %j', TypeError);
E('ERR_TLS_RENEGOTIATE', 'Attempt to renegotiate TLS session failed', Error); E('ERR_TLS_RENEGOTIATE', 'Attempt to renegotiate TLS session failed', Error);
E('ERR_TLS_RENEGOTIATION_DISABLED', E('ERR_TLS_RENEGOTIATION_DISABLED',
'TLS session renegotiation disabled for this socket', Error); 'TLS session renegotiation disabled for this socket', Error);

View File

@ -31,6 +31,7 @@ internalUtil.assertCrypto();
const { isArrayBufferView } = require('internal/util/types'); const { isArrayBufferView } = require('internal/util/types');
const net = require('net'); const net = require('net');
const { getOptionValue } = require('internal/options');
const url = require('url'); const url = require('url');
const binding = internalBinding('crypto'); const binding = internalBinding('crypto');
const { Buffer } = require('buffer'); const { Buffer } = require('buffer');
@ -53,6 +54,15 @@ exports.DEFAULT_CIPHERS =
exports.DEFAULT_ECDH_CURVE = 'auto'; exports.DEFAULT_ECDH_CURVE = 'auto';
exports.DEFAULT_MAX_VERSION = 'TLSv1.2';
if (getOptionValue('--tls-v1.0'))
exports.DEFAULT_MIN_VERSION = 'TLSv1';
else if (getOptionValue('--tls-v1.1'))
exports.DEFAULT_MIN_VERSION = 'TLSv1.1';
else
exports.DEFAULT_MIN_VERSION = 'TLSv1.2';
exports.getCiphers = internalUtil.cachedResult( exports.getCiphers = internalUtil.cachedResult(
() => internalUtil.filterDuplicateStrings(binding.getSSLCiphers(), true) () => internalUtil.filterDuplicateStrings(binding.getSSLCiphers(), true)
); );

View File

@ -1237,6 +1237,10 @@ void DefineCryptoConstants(Local<Object> target) {
NODE_DEFINE_STRING_CONSTANT(target, NODE_DEFINE_STRING_CONSTANT(target,
"defaultCipherList", "defaultCipherList",
per_process_opts->tls_cipher_list.c_str()); per_process_opts->tls_cipher_list.c_str());
NODE_DEFINE_CONSTANT(target, TLS1_VERSION);
NODE_DEFINE_CONSTANT(target, TLS1_1_VERSION);
NODE_DEFINE_CONSTANT(target, TLS1_2_VERSION);
#endif #endif
NODE_DEFINE_CONSTANT(target, INT_MAX); NODE_DEFINE_CONSTANT(target, INT_MAX);
} }

View File

@ -405,14 +405,15 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
Environment* env = sc->env(); Environment* env = sc->env();
int min_version = TLS1_2_VERSION; CHECK_EQ(args.Length(), 3);
int max_version = 0; CHECK(args[1]->IsInt32());
CHECK(args[2]->IsInt32());
int min_version = args[1].As<Int32>()->Value();
int max_version = args[2].As<Int32>()->Value();
const SSL_METHOD* method = TLS_method(); const SSL_METHOD* method = TLS_method();
if (env->options()->tls_v1_1) min_version = TLS1_1_VERSION; if (args[0]->IsString()) {
if (env->options()->tls_v1_0) min_version = TLS1_VERSION;
if (args.Length() == 1 && args[0]->IsString()) {
const node::Utf8Value sslmethod(env->isolate(), args[0]); const node::Utf8Value sslmethod(env->isolate(), args[0]);
// Note that SSLv2 and SSLv3 are disallowed but SSLv23_method and friends // Note that SSLv2 and SSLv3 are disallowed but SSLv23_method and friends
@ -509,6 +510,7 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
SSL_CTX_set_min_proto_version(sc->ctx_.get(), min_version); SSL_CTX_set_min_proto_version(sc->ctx_.get(), min_version);
SSL_CTX_set_max_proto_version(sc->ctx_.get(), max_version); SSL_CTX_set_max_proto_version(sc->ctx_.get(), max_version);
// OpenSSL 1.1.0 changed the ticket key size, but the OpenSSL 1.0.x size was // OpenSSL 1.1.0 changed the ticket key size, but the OpenSSL 1.0.x size was
// exposed in the public API. To retain compatibility, install a callback // exposed in the public API. To retain compatibility, install a callback
// which restores the old algorithm. // which restores the old algorithm.

View File

@ -46,6 +46,7 @@ exports.connect = function connect(options, callback) {
const client = {}; const client = {};
const pair = { server, client }; const pair = { server, client };
try {
tls.createServer(options.server, function(conn) { tls.createServer(options.server, function(conn) {
server.conn = conn; server.conn = conn;
conn.pipe(conn); conn.pipe(conn);
@ -57,6 +58,7 @@ exports.connect = function connect(options, callback) {
port: this.address().port, port: this.address().port,
}, options.client); }, options.client);
try {
tls.connect(optClient) tls.connect(optClient)
.on('secureConnect', function() { .on('secureConnect', function() {
client.conn = this; client.conn = this;
@ -67,7 +69,22 @@ exports.connect = function connect(options, callback) {
client.conn = this; client.conn = this;
maybeCallback(); maybeCallback();
}); });
} catch (err) {
client.err = err;
// The server won't get a connection, we are done.
callback(err, pair, cleanup);
callback = null;
}
}).on('tlsClientError', function(err, sock) {
server.conn = sock;
server.err = err;
maybeCallback();
}); });
} catch (err) {
// Invalid options can throw, report the error.
pair.server.err = err;
callback(err, pair, () => {});
}
function maybeCallback() { function maybeCallback() {
if (!callback) if (!callback)
@ -76,6 +93,8 @@ exports.connect = function connect(options, callback) {
const err = pair.client.err || pair.server.err; const err = pair.client.err || pair.server.err;
callback(err, pair, cleanup); callback(err, pair, cleanup);
callback = null; callback = null;
}
}
function cleanup() { function cleanup() {
if (server.server) if (server.server)
@ -84,5 +103,3 @@ exports.connect = function connect(options, callback) {
client.conn.end(); client.conn.end();
} }
} }
}
}

View File

@ -12,7 +12,7 @@ const agent = new https.Agent();
// empty options // empty options
assert.strictEqual( assert.strictEqual(
agent.getName({}), agent.getName({}),
'localhost:::::::::::::::::' 'localhost:::::::::::::::::::'
); );
// pass all options arguments // pass all options arguments
@ -40,5 +40,5 @@ const options = {
assert.strictEqual( assert.strictEqual(
agent.getName(options), agent.getName(options),
'0.0.0.0:443:192.168.1.1:ca:cert:dynamic:ciphers:key:pfx:false:localhost:' + '0.0.0.0:443:192.168.1.1:ca:cert:dynamic:ciphers:key:pfx:false:localhost:' +
'secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext' '::secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext'
); );

View File

@ -0,0 +1,15 @@
// Flags: --tls-v1.0 --tls-v1.1
'use strict';
const common = require('../common');
if (!common.hasCrypto) common.skip('missing crypto');
// Check that `node --tls-v1.0` is supported, and overrides --tls-v1.1.
const assert = require('assert');
const tls = require('tls');
assert.strictEqual(tls.DEFAULT_MAX_VERSION, 'TLSv1.2');
assert.strictEqual(tls.DEFAULT_MIN_VERSION, 'TLSv1');
// Check the min-max version protocol versions against these CLI settings.
require('./test-tls-min-max-version.js');

View File

@ -0,0 +1,15 @@
// Flags: --tls-v1.1
'use strict';
const common = require('../common');
if (!common.hasCrypto) common.skip('missing crypto');
// Check that node `--tls-v1.1` is supported.
const assert = require('assert');
const tls = require('tls');
assert.strictEqual(tls.DEFAULT_MAX_VERSION, 'TLSv1.2');
assert.strictEqual(tls.DEFAULT_MIN_VERSION, 'TLSv1.1');
// Check the min-max version protocol versions against these CLI settings.
require('./test-tls-min-max-version.js');

View File

@ -0,0 +1,146 @@
'use strict';
const common = require('../common');
const fixtures = require('../common/fixtures');
// Check min/max protocol versions.
const {
assert, connect, keys, tls
} = require(fixtures.path('tls-connect'));
const DEFAULT_MIN_VERSION = tls.DEFAULT_MIN_VERSION;
function test(cmin, cmax, cprot, smin, smax, sprot, expect) {
connect({
client: {
checkServerIdentity: (servername, cert) => { },
ca: `${keys.agent1.cert}\n${keys.agent6.ca}`,
minVersion: cmin,
maxVersion: cmax,
secureProtocol: cprot,
},
server: {
cert: keys.agent6.cert,
key: keys.agent6.key,
minVersion: smin,
maxVersion: smax,
secureProtocol: sprot,
},
}, common.mustCall((err, pair, cleanup) => {
if (expect && !expect.match(/^TLS/)) {
assert(err.message.match(expect));
return cleanup();
}
if (expect) {
assert.ifError(pair.server.err);
assert.ifError(pair.client.err);
assert(pair.server.conn);
assert(pair.client.conn);
assert.strictEqual(pair.client.conn.getProtocol(), expect);
assert.strictEqual(pair.server.conn.getProtocol(), expect);
return cleanup();
}
assert(pair.server.err);
assert(pair.client.err);
return cleanup();
}));
}
const U = undefined;
// Default protocol is TLSv1.2.
test(U, U, U, U, U, U, 'TLSv1.2');
// Insecure or invalid protocols cannot be enabled.
test(U, U, U, U, U, 'SSLv2_method', 'SSLv2 methods disabled');
test(U, U, U, U, U, 'SSLv3_method', 'SSLv3 methods disabled');
test(U, U, 'SSLv2_method', U, U, U, 'SSLv2 methods disabled');
test(U, U, 'SSLv3_method', U, U, U, 'SSLv3 methods disabled');
test(U, U, 'hokey-pokey', U, U, U, 'Unknown method');
test(U, U, U, U, U, 'hokey-pokey', 'Unknown method');
// Cannot use secureProtocol and min/max versions simultaneously.
test(U, U, U, U, 'TLSv1.2', 'TLS1_2_method', 'conflicts with secureProtocol');
test(U, U, U, 'TLSv1.2', U, 'TLS1_2_method', 'conflicts with secureProtocol');
test(U, 'TLSv1.2', 'TLS1_2_method', U, U, U, 'conflicts with secureProtocol');
test('TLSv1.2', U, 'TLS1_2_method', U, U, U, 'conflicts with secureProtocol');
// TLS_method means "any supported protocol".
test(U, U, 'TLSv1_2_method', U, U, 'TLS_method', 'TLSv1.2');
test(U, U, 'TLSv1_1_method', U, U, 'TLS_method', 'TLSv1.1');
test(U, U, 'TLSv1_method', U, U, 'TLS_method', 'TLSv1');
test(U, U, 'TLS_method', U, U, 'TLSv1_2_method', 'TLSv1.2');
test(U, U, 'TLS_method', U, U, 'TLSv1_1_method', 'TLSv1.1');
test(U, U, 'TLS_method', U, U, 'TLSv1_method', 'TLSv1');
// SSLv23 also means "any supported protocol" greater than the default
// minimum (which is configurable via command line).
test(U, U, 'TLSv1_2_method', U, U, 'SSLv23_method', 'TLSv1.2');
if (DEFAULT_MIN_VERSION === 'TLSv1.2') {
test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method', null);
test(U, U, 'TLSv1_method', U, U, 'SSLv23_method', null);
test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method', null);
test(U, U, 'SSLv23_method', U, U, 'TLSv1_method', null);
}
if (DEFAULT_MIN_VERSION === 'TLSv1.1') {
test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method', 'TLSv1.1');
test(U, U, 'TLSv1_method', U, U, 'SSLv23_method', null);
test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method', 'TLSv1.1');
test(U, U, 'SSLv23_method', U, U, 'TLSv1_method', null);
}
if (DEFAULT_MIN_VERSION === 'TLSv1') {
test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method', 'TLSv1.1');
test(U, U, 'TLSv1_method', U, U, 'SSLv23_method', 'TLSv1');
test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method', 'TLSv1.1');
test(U, U, 'SSLv23_method', U, U, 'TLSv1_method', 'TLSv1');
}
// TLSv1 thru TLSv1.2 are only supported with explicit configuration with API or
// CLI (--tls-v1.0 and --tls-v1.1).
test(U, U, 'TLSv1_2_method', U, U, 'TLSv1_2_method', 'TLSv1.2');
test(U, U, 'TLSv1_1_method', U, U, 'TLSv1_1_method', 'TLSv1.1');
test(U, U, 'TLSv1_method', U, U, 'TLSv1_method', 'TLSv1');
// The default default.
if (DEFAULT_MIN_VERSION === 'TLSv1.2') {
test(U, U, 'TLSv1_1_method', U, U, U, null);
test(U, U, 'TLSv1_method', U, U, U, null);
test(U, U, U, U, U, 'TLSv1_1_method', null);
test(U, U, U, U, U, 'TLSv1_method', null);
}
// The default with --tls-v1.1.
if (DEFAULT_MIN_VERSION === 'TLSv1.1') {
test(U, U, 'TLSv1_1_method', U, U, U, 'TLSv1.1');
test(U, U, 'TLSv1_method', U, U, U, null);
test(U, U, U, U, U, 'TLSv1_1_method', 'TLSv1.1');
test(U, U, U, U, U, 'TLSv1_method', null);
}
// The default with --tls-v1.0.
if (DEFAULT_MIN_VERSION === 'TLSv1') {
test(U, U, 'TLSv1_1_method', U, U, U, 'TLSv1.1');
test(U, U, 'TLSv1_method', U, U, U, 'TLSv1');
test(U, U, U, U, U, 'TLSv1_1_method', 'TLSv1.1');
test(U, U, U, U, U, 'TLSv1_method', 'TLSv1');
}
// TLS min/max are respected when set with no secureProtocol.
test('TLSv1', 'TLSv1.2', U, U, U, 'TLSv1_method', 'TLSv1');
test('TLSv1', 'TLSv1.2', U, U, U, 'TLSv1_1_method', 'TLSv1.1');
test('TLSv1', 'TLSv1.2', U, U, U, 'TLSv1_2_method', 'TLSv1.2');
test(U, U, 'TLSv1_method', 'TLSv1', 'TLSv1.2', U, 'TLSv1');
test(U, U, 'TLSv1_1_method', 'TLSv1', 'TLSv1.2', U, 'TLSv1.1');
test(U, U, 'TLSv1_2_method', 'TLSv1', 'TLSv1.2', U, 'TLSv1.2');
test('TLSv1', 'TLSv1.1', U, 'TLSv1', 'TLSv1.2', U, 'TLSv1.1');
test('TLSv1', 'TLSv1.2', U, 'TLSv1', 'TLSv1.1', U, 'TLSv1.1');
test('TLSv1', 'TLSv1', U, 'TLSv1', 'TLSv1.1', U, 'TLSv1');
test('TLSv1', 'TLSv1.2', U, 'TLSv1', 'TLSv1', U, 'TLSv1');
test('TLSv1.1', 'TLSv1.1', U, 'TLSv1', 'TLSv1.2', U, 'TLSv1.1');
test('TLSv1', 'TLSv1.2', U, 'TLSv1.1', 'TLSv1.1', U, 'TLSv1.1');