tls: support Uint8Arrays for protocol list buffers

PR-URL: https://github.com/nodejs/node/pull/11984
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Anna Henningsen 2017-03-22 07:42:04 +01:00
parent 2dc1053b0a
commit c3efe72669
No known key found for this signature in database
GPG Key ID: D8B9F5AEAE84E4CF
3 changed files with 51 additions and 16 deletions

View File

@ -752,6 +752,10 @@ decrease overall server throughput.
<!-- YAML <!-- YAML
added: v0.11.3 added: v0.11.3
changes: changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/11984
description: The `ALPNProtocols` and `NPNProtocols` options can
be `Uint8Array`s now.
- version: v5.3.0, v4.7.0 - version: v5.3.0, v4.7.0
pr-url: https://github.com/nodejs/node/pull/4246 pr-url: https://github.com/nodejs/node/pull/4246
description: The `secureContext` option is supported now. description: The `secureContext` option is supported now.
@ -776,16 +780,18 @@ changes:
against the list of supplied CAs. An `'error'` event is emitted if against the list of supplied CAs. An `'error'` event is emitted if
verification fails; `err.code` contains the OpenSSL error code. Defaults to verification fails; `err.code` contains the OpenSSL error code. Defaults to
`true`. `true`.
* `NPNProtocols` {string[]|Buffer[]} An array of strings or `Buffer`s * `NPNProtocols` {string[]|Buffer[]|Uint8Array[]|Buffer|Uint8Array}
containing supported NPN protocols. `Buffer`s should have the format An array of strings, Buffer`s or `Uint8Array`s, or a single `Buffer` or
`[len][name][len][name]...` e.g. `0x05hello0x05world`, where the first `Uint8Array` containing supported NPN protocols. `Buffer`s should have the
byte is the length of the next protocol name. Passing an array is usually format `[len][name][len][name]...` e.g. `0x05hello0x05world`, where the
much simpler, e.g. `['hello', 'world']`. first byte is the length of the next protocol name. Passing an array is
* `ALPNProtocols`: {string[]|Buffer[]} An array of strings or `Buffer`s usually much simpler, e.g. `['hello', 'world']`.
containing the supported ALPN protocols. `Buffer`s should have the format * `ALPNProtocols`: {string[]|Buffer[]|Uint8Array[]|Buffer|Uint8Array}
`[len][name][len][name]...` e.g. `0x05hello0x05world`, where the first byte An array of strings, `Buffer`s or `Uint8Array`s, or a single `Buffer` or
is the length of the next protocol name. Passing an array is usually much `Uint8Array` containing the supported ALPN protocols. `Buffer`s should have
simpler: `['hello', 'world']`.) the format `[len][name][len][name]...` e.g. `0x05hello0x05world`, where the
first byte is the length of the next protocol name. Passing an array is
usually much simpler, e.g. `['hello', 'world']`.
* `servername`: {string} Server name for the SNI (Server Name Indication) TLS * `servername`: {string} Server name for the SNI (Server Name Indication) TLS
extension. extension.
* `checkServerIdentity(servername, cert)` {Function} A callback function * `checkServerIdentity(servername, cert)` {Function} A callback function
@ -1002,6 +1008,10 @@ publicly trusted list of CAs as given in
<!-- YAML <!-- YAML
added: v0.3.2 added: v0.3.2
changes: changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/11984
description: The `ALPNProtocols` and `NPNProtocols` options can
be `Uint8Array`s now.
- version: v5.0.0 - version: v5.0.0
pr-url: https://github.com/nodejs/node/pull/2564 pr-url: https://github.com/nodejs/node/pull/2564
description: ALPN options are supported now. description: ALPN options are supported now.
@ -1018,10 +1028,20 @@ changes:
* `rejectUnauthorized` {boolean} If not `false` the server will reject any * `rejectUnauthorized` {boolean} If not `false` the server will reject any
connection which is not authorized with the list of supplied CAs. This connection which is not authorized with the list of supplied CAs. This
option only has an effect if `requestCert` is `true`. Defaults to `true`. option only has an effect if `requestCert` is `true`. Defaults to `true`.
* `NPNProtocols` {string[]|Buffer} An array of strings or a `Buffer` naming * `NPNProtocols` {string[]|Buffer[]|Uint8Array[]|Buffer|Uint8Array}
possible NPN protocols. (Protocols should be ordered by their priority.) An array of strings, Buffer`s or `Uint8Array`s, or a single `Buffer` or
* `ALPNProtocols` {string[]|Buffer} An array of strings or a `Buffer` naming `Uint8Array` containing supported NPN protocols. `Buffer`s should have the
possible ALPN protocols. (Protocols should be ordered by their priority.) format `[len][name][len][name]...` e.g. `0x05hello0x05world`, where the
first byte is the length of the next protocol name. Passing an array is
usually much simpler, e.g. `['hello', 'world']`.
(Protocols should be ordered by their priority.)
* `ALPNProtocols`: {string[]|Buffer[]|Uint8Array[]|Buffer|Uint8Array}
An array of strings, `Buffer`s or `Uint8Array`s, or a single `Buffer` or
`Uint8Array` containing the supported ALPN protocols. `Buffer`s should have
the format `[len][name][len][name]...` e.g. `0x05hello0x05world`, where the
first byte is the length of the next protocol name. Passing an array is
usually much simpler, e.g. `['hello', 'world']`.
(Protocols should be ordered by their priority.)
When the server receives both NPN and ALPN extensions from the client, When the server receives both NPN and ALPN extensions from the client,
ALPN takes precedence over NPN and the server does not send an NPN ALPN takes precedence over NPN and the server does not send an NPN
extension to the client. extension to the client.

View File

@ -28,6 +28,7 @@ const net = require('net');
const url = require('url'); const url = require('url');
const binding = process.binding('crypto'); const binding = process.binding('crypto');
const Buffer = require('buffer').Buffer; const Buffer = require('buffer').Buffer;
const { isUint8Array } = process.binding('util');
// Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations
// every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more
@ -71,7 +72,7 @@ exports.convertNPNProtocols = function(protocols, out) {
// If protocols is Array - translate it into buffer // If protocols is Array - translate it into buffer
if (Array.isArray(protocols)) { if (Array.isArray(protocols)) {
out.NPNProtocols = convertProtocols(protocols); out.NPNProtocols = convertProtocols(protocols);
} else if (protocols instanceof Buffer) { } else if (isUint8Array(protocols)) {
// Copy new buffer not to be modified by user. // Copy new buffer not to be modified by user.
out.NPNProtocols = Buffer.from(protocols); out.NPNProtocols = Buffer.from(protocols);
} }
@ -81,7 +82,7 @@ exports.convertALPNProtocols = function(protocols, out) {
// If protocols is Array - translate it into buffer // If protocols is Array - translate it into buffer
if (Array.isArray(protocols)) { if (Array.isArray(protocols)) {
out.ALPNProtocols = convertProtocols(protocols); out.ALPNProtocols = convertProtocols(protocols);
} else if (protocols instanceof Buffer) { } else if (isUint8Array(protocols)) {
// Copy new buffer not to be modified by user. // Copy new buffer not to be modified by user.
out.ALPNProtocols = Buffer.from(protocols); out.ALPNProtocols = Buffer.from(protocols);
} }

View File

@ -56,3 +56,17 @@ assert.throws(() => tls.createSecurePair({}),
assert(buffer.equals(Buffer.from('abcd'))); assert(buffer.equals(Buffer.from('abcd')));
assert(out.NPNProtocols.equals(Buffer.from('efgh'))); assert(out.NPNProtocols.equals(Buffer.from('efgh')));
} }
{
const buffer = new Uint8Array(Buffer.from('abcd'));
const out = {};
tls.convertALPNProtocols(buffer, out);
assert(out.ALPNProtocols.equals(Buffer.from('abcd')));
}
{
const buffer = new Uint8Array(Buffer.from('abcd'));
const out = {};
tls.convertNPNProtocols(buffer, out);
assert(out.NPNProtocols.equals(Buffer.from('abcd')));
}