Skip to content

Commit 56b2a09

Browse files
committedNov 12, 2018
tls: add min/max_version and their defaults
1 parent c907c46 commit 56b2a09

File tree

7 files changed

+84
-8
lines changed

7 files changed

+84
-8
lines changed
 

‎doc/api/tls.md

+14
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,10 @@ changes:
10501050
pr-url: https://github.com/nodejs/node/pull/4099
10511051
description: The `ca` option can now be a single string containing multiple
10521052
CA certificates.
1053+
- version: XXX
1054+
pr-url: XXX
1055+
description: The `min_version` and `max_version` can be used to restrict
1056+
the allowed TLS protocol versions.
10531057
-->
10541058

10551059
* `options` {Object}
@@ -1110,6 +1114,16 @@ changes:
11101114
passphrase: <string>]}`. The object form can only occur in an array.
11111115
`object.passphrase` is optional. Encrypted keys will be decrypted with
11121116
`object.passphrase` if provided, or `options.passphrase` if it is not.
1117+
* `max_version`: Maximum TLS version to allow. One of `'TLSv1.3'`, `TLSv1.2'`,
1118+
`'TLSv1.1'`, or `'TLSv1'`. Optional, defaults to `'TLSv1.2'`. Note that
1119+
TLS1.3 is not currently supported, do not attempt to allow it. If
1120+
`secureProtocol` is used to select a specific protocol version,
1121+
`max_version` will be ignored.
1122+
* `min_version`: Minimum TLS version to allow. One of `'TLSv1.3'`, `TLSv1.2'`,
1123+
`'TLSv1.1'`, or `'TLSv1'`. Optional, defaults to `'TLSv1'`. Note that
1124+
TLS1.3 is not currently supported, do not attempt to allow it. If
1125+
`secureProtocol` is used to select a specific protocol version,
1126+
`min_version` will be ignored.
11131127
* `passphrase` {string} Shared passphrase used for a single private key and/or
11141128
a PFX.
11151129
* `pfx` {string|string[]|Buffer|Buffer[]|Object[]} PFX or PKCS12 encoded

‎lib/_tls_common.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,22 @@ const {
2828
ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED,
2929
ERR_INVALID_ARG_TYPE
3030
} = require('internal/errors').codes;
31-
3231
const { SSL_OP_CIPHER_SERVER_PREFERENCE } = internalBinding('constants').crypto;
3332

3433
// Lazily loaded from internal/crypto/util.
3534
let toBuf = null;
3635

36+
3737
const { SecureContext: NativeSecureContext } = internalBinding('crypto');
38-
function SecureContext(secureProtocol, secureOptions) {
38+
39+
function SecureContext(secureProtocol, secureOptions, min_version,
40+
max_version) {
3941
if (!(this instanceof SecureContext)) {
4042
return new SecureContext(secureProtocol, secureOptions);
4143
}
4244

4345
this.context = new NativeSecureContext();
44-
this.context.init(secureProtocol);
46+
this.context.init(min_version, max_version, secureProtocol);
4547

4648
if (secureOptions) this.context.setOptions(secureOptions);
4749
}
@@ -66,7 +68,9 @@ exports.createSecureContext = function createSecureContext(options) {
6668
if (options.honorCipherOrder)
6769
secureOptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
6870

69-
const c = new SecureContext(options.secureProtocol, secureOptions);
71+
const c = new SecureContext(options.secureProtocol, secureOptions,
72+
options.min_version || tls.DEFAULT_MIN_VERSION,
73+
options.max_version || tls.DEFAULT_MAX_VERSION);
7074
var i;
7175
var val;
7276

‎lib/_tls_wrap.js

+14
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,16 @@ Server.prototype.setSecureContext = function(options) {
904904
else
905905
this.ca = undefined;
906906

907+
if (options.min_version)
908+
this.min_version = options.min_version;
909+
else
910+
this.min_version = undefined;
911+
912+
if (options.max_version)
913+
this.max_version = options.max_version;
914+
else
915+
this.max_version = undefined;
916+
907917
if (options.secureProtocol)
908918
this.secureProtocol = options.secureProtocol;
909919
else
@@ -960,6 +970,8 @@ Server.prototype.setSecureContext = function(options) {
960970
ciphers: this.ciphers,
961971
ecdhCurve: this.ecdhCurve,
962972
dhparam: this.dhparam,
973+
min_version: this.min_version,
974+
max_version: this.max_version,
963975
secureProtocol: this.secureProtocol,
964976
secureOptions: this.secureOptions,
965977
honorCipherOrder: this.honorCipherOrder,
@@ -1012,6 +1024,8 @@ Server.prototype.setOptions = util.deprecate(function(options) {
10121024
if (options.clientCertEngine)
10131025
this.clientCertEngine = options.clientCertEngine;
10141026
if (options.ca) this.ca = options.ca;
1027+
if (options.min_version) this.min_version = options.min_version;
1028+
if (options.max_version) this.max_version = options.max_version;
10151029
if (options.secureProtocol) this.secureProtocol = options.secureProtocol;
10161030
if (options.crl) this.crl = options.crl;
10171031
if (options.ciphers) this.ciphers = options.ciphers;

‎lib/https.js

+8
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,14 @@ Agent.prototype.getName = function getName(options) {
186186
if (options.servername && options.servername !== options.host)
187187
name += options.servername;
188188

189+
name += ':';
190+
if (options.min_version)
191+
name += options.min_version;
192+
193+
name += ':';
194+
if (options.max_version)
195+
name += options.max_version;
196+
189197
name += ':';
190198
if (options.secureProtocol)
191199
name += options.secureProtocol;

‎lib/tls.js

+7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ exports.DEFAULT_CIPHERS =
5353

5454
exports.DEFAULT_ECDH_CURVE = 'auto';
5555

56+
// Disable TLS1.3 by default. The only reason for enabling it for now is to work
57+
// on fixing cipher suite incompatibilities with TLS1.2 that prevent node from
58+
// working with TLS1.3 in OpenSSL 1.1.1.
59+
exports.DEFAULT_MAX_VERSION = 'TLSv1.2';
60+
61+
exports.DEFAULT_MIN_VERSION = 'TLSv1';
62+
5663
exports.getCiphers = internalUtil.cachedResult(
5764
() => internalUtil.filterDuplicateStrings(binding.getSSLCiphers(), true)
5865
);

‎src/node_crypto.cc

+31-2
Original file line numberDiff line numberDiff line change
@@ -391,17 +391,46 @@ void SecureContext::New(const FunctionCallbackInfo<Value>& args) {
391391
}
392392

393393

394+
int string_to_tls_protocol(const char* version_str) {
395+
int version;
396+
397+
if (strcmp(version_str, "TLSv1.3") == 0) {
398+
version = TLS1_3_VERSION;
399+
} else if (strcmp(version_str, "TLSv1.2") == 0) {
400+
version = TLS1_2_VERSION;
401+
} else if (strcmp(version_str, "TLSv1.1") == 0) {
402+
version = TLS1_1_VERSION;
403+
} else if (strcmp(version_str, "TLSv1") == 0) {
404+
version = TLS1_VERSION;
405+
} else {
406+
version = 0;
407+
}
408+
return version;
409+
}
410+
411+
394412
void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
395413
SecureContext* sc;
396414
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
397415
Environment* env = sc->env();
398416

399417
int min_version = 0;
400418
int max_version = 0;
419+
420+
if (args[0]->IsString()) {
421+
const node::Utf8Value min(env->isolate(), args[0]);
422+
min_version = string_to_tls_protocol(*min);
423+
}
424+
425+
if (args[1]->IsString()) {
426+
const node::Utf8Value max(env->isolate(), args[1]);
427+
max_version = string_to_tls_protocol(*max);
428+
}
429+
401430
const SSL_METHOD* method = TLS_method();
402431

403-
if (args.Length() == 1 && args[0]->IsString()) {
404-
const node::Utf8Value sslmethod(env->isolate(), args[0]);
432+
if (args.Length() == 3 && args[2]->IsString()) {
433+
const node::Utf8Value sslmethod(env->isolate(), args[2]);
405434

406435
// Note that SSLv2 and SSLv3 are disallowed but SSLv23_method and friends
407436
// are still accepted. They are OpenSSL's way of saying that all known

‎test/parallel/test-https-agent-getname.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const agent = new https.Agent();
1212
// empty options
1313
assert.strictEqual(
1414
agent.getName({}),
15-
'localhost:::::::::::::::::'
15+
'localhost:::::::::::::::::::'
1616
);
1717

1818
// pass all options arguments
@@ -39,5 +39,5 @@ const options = {
3939
assert.strictEqual(
4040
agent.getName(options),
4141
'0.0.0.0:443:192.168.1.1:ca:cert::ciphers:key:pfx:false:localhost:' +
42-
'secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext'
42+
'::secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext'
4343
);

0 commit comments

Comments
 (0)
Please sign in to comment.