mirror of
https://github.com/oven-sh/bun
synced 2026-02-05 16:38:55 +00:00
Compare commits
57 Commits
dylan/pyth
...
pfg/tls
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d787626f18 | ||
|
|
ea31ae1d2e | ||
|
|
a02d6d48b9 | ||
|
|
ebbbba0fa6 | ||
|
|
7e97cd447e | ||
|
|
10616499a7 | ||
|
|
cc08966171 | ||
|
|
4b7b5dbdca | ||
|
|
3d9534414e | ||
|
|
47abb06811 | ||
|
|
d43cffbed3 | ||
|
|
46e087ee0c | ||
|
|
ba12a3dfd4 | ||
|
|
483afffccc | ||
|
|
979cfd96f0 | ||
|
|
645fa28843 | ||
|
|
9162bf45d0 | ||
|
|
80e9242a0d | ||
|
|
82cf920a51 | ||
|
|
ee07032fd9 | ||
|
|
347d350405 | ||
|
|
8c85826c7b | ||
|
|
1bfd479aad | ||
|
|
a28708ea54 | ||
|
|
80498e2418 | ||
|
|
361a3592e5 | ||
|
|
4a8828d1aa | ||
|
|
a286134233 | ||
|
|
3ee7649f95 | ||
|
|
4848a2d0b7 | ||
|
|
e3ebd4177a | ||
|
|
818f3bb83f | ||
|
|
b3cf2df234 | ||
|
|
9d40c62901 | ||
|
|
e331f00c7e | ||
|
|
271ee072ef | ||
|
|
57cff5520b | ||
|
|
3e938e0fe6 | ||
|
|
c074fbaa8d | ||
|
|
0191f65e36 | ||
|
|
c585ac3a92 | ||
|
|
eed575da7e | ||
|
|
bf3086abf8 | ||
|
|
8ecdabdcd2 | ||
|
|
4deec54426 | ||
|
|
0deefe33f2 | ||
|
|
b949e2062a | ||
|
|
a99f2e5071 | ||
|
|
b3d623c091 | ||
|
|
c12a7ef612 | ||
|
|
0b1ada3d12 | ||
|
|
2fadf4cd03 | ||
|
|
9496469617 | ||
|
|
24bc337b0a | ||
|
|
15c7cc6008 | ||
|
|
132f0e75d3 | ||
|
|
c69c7ab2a8 |
231
categories.txt
Normal file
231
categories.txt
Normal file
@@ -0,0 +1,231 @@
|
||||
```js
|
||||
doc = (top list)
|
||||
doc2 = (electron list)
|
||||
{
|
||||
|
||||
[...document.querySelectorAll(".test-link")].forEach(t => {
|
||||
const name = t.lastChild.nodeValue.trim().slice(0, -3);
|
||||
|
||||
if(doc2.includes(name)) {
|
||||
t.style.color = "red";
|
||||
}else if(doc.includes(name)) {
|
||||
t.style.color = "black";
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
# TODO CHECK:
|
||||
|
||||
# max version env vars, not investigated.
|
||||
|
||||
parallel/test-tls-client-reject-12.js
|
||||
parallel/test-tls-ticket-12.js
|
||||
parallel/test-tls-client-resume-12.js
|
||||
parallel/test-tls-destroy-stream-12.js
|
||||
parallel/test-tls-net-socket-keepalive-12.js
|
||||
parallel/test-tls-keylog-tlsv13.js
|
||||
parallel/test-tls-cli-min-max-conflict.js
|
||||
|
||||
# trivial
|
||||
|
||||
parallel/test-tls-external-accessor.js
|
||||
- we don't support `_external`, but we pass the spirit of the test. trivial 'fix'
|
||||
parallel/test-tls-destroy-stream.js
|
||||
parallel/test-tls-socket-close.js
|
||||
parallel/test-double-tls-client.js (this one maybe not as easy, but it is somewhat related)
|
||||
parallel/test-tls-server-capture-rejection.js (maybe related? async createServer callback does not work with events.captureRejections)
|
||||
- the test calls `.emit("connection")` on the tlsServer. In node, this calls the connection
|
||||
handler but in bun it does not. Switch tls to use emit("connection") rather than
|
||||
calling the connection listener directly, and add .on('connection') in the constructor
|
||||
like node does.
|
||||
```diff
|
||||
if (typeof options === "function") {
|
||||
connectionListener = options;
|
||||
options = {};
|
||||
+this.on("connection", connectionListener);
|
||||
} else if (options == null || typeof options === "object") {
|
||||
options = { ...options };
|
||||
+this.on("connection", connectionListener);
|
||||
} else {
|
||||
throw $ERR_INVALID_ARG_TYPE("options", ["Object", "Function"], options);
|
||||
}
|
||||
|
||||
- if (typeof connectionListener === "function") {
|
||||
- this.pauseOnConnect = pauseOnConnect;
|
||||
- if (!isTLS) {
|
||||
- connectionListener.$call(self, _socket);
|
||||
- }
|
||||
- }
|
||||
|
||||
also check what to do here
|
||||
|
||||
const connectionListener = server[bunSocketServerOptions]?.connectionListener;
|
||||
if (typeof connectionListener === "function") {
|
||||
connectionListener.$call(server, self);
|
||||
}
|
||||
server.emit("secureConnection", self);
|
||||
```
|
||||
parallel/test-tls-wrap-event-emmiter.js
|
||||
- missing error for passing plain eventEmitter to TlsSocket constructor
|
||||
|
||||
# probably easy
|
||||
|
||||
parallel/test-tls-exportkeyingmaterial.js
|
||||
- exportKeyingMaterial emits as uncaughtException rather than thrown error
|
||||
parallel/test-tls-cert-chains-in-ca.js
|
||||
parallel/test-tls-env-extra-ca.js
|
||||
- checkServerIdentity callback is not implemented
|
||||
parallel/test-tls-basic-validations.js
|
||||
- 12 mismatched errors
|
||||
parallel/test-tls-error-servername.js
|
||||
- 2 mismatched errors
|
||||
parallel/test-tls-client-allow-partial-trust-chain.js
|
||||
- support allowPartialTrustChain
|
||||
parallel/test-tls-env-bad-extra-ca.js
|
||||
- emit a warning when the value in NODE_EXTRA_CA_CERTS is ignored because it fails to load
|
||||
- this is a little bit hard to do because currently we handle that in us_internal_init_root_certs with getenv,
|
||||
but we can't emit a warning from there. we would have to have it call out to bun code to emit the warning
|
||||
|
||||
# categorize
|
||||
|
||||
parallel/test-tls-connect-allow-half-open-option.js
|
||||
- with allowHalfOpen, if the server ends its socket, it should still be able to receive a message
|
||||
parallel/test-tls-server-parent-constructor-options.js
|
||||
- with pauseOnConnect, the client is never connecting
|
||||
parallel/test-tls-get-ca-certificates-system.js
|
||||
parallel/test-tls-get-ca-certificates-default.js
|
||||
parallel/test-tls-get-ca-certificates-error.js
|
||||
parallel/test-tls-get-ca-certificates-extra-empty.js
|
||||
parallel/test-tls-get-ca-certificates-bundled.js
|
||||
parallel/test-tls-get-ca-certificates-extra-subset.js
|
||||
parallel/test-tls-get-ca-certificates-system-without-flag.js
|
||||
parallel/test-tls-get-ca-certificates-bundled-subset.js
|
||||
parallel/test-tls-get-ca-certificates-extra.js
|
||||
- tls.getCACertificates is not implemented
|
||||
parallel/test-tls-server-setkeycert.js
|
||||
- some kind of problem with getPeerX509Certificate?
|
||||
parallel/test-tls-enable-keylog-cli.js
|
||||
- support --tls-keylog cli flag
|
||||
parallel/test-tls-cert-chains-concat.js
|
||||
- issuerCertificate is not defined?
|
||||
parallel/test-tls-streamwrap-buffersize.js
|
||||
- bufferSize is wrong. also it is deprecated.
|
||||
parallel/test-tls-clientcertengine-invalid-arg-type.js
|
||||
parallel/test-tls-socket-default-options.js
|
||||
parallel/test-tls-set-secure-context.js
|
||||
- createSecureContext (kai)
|
||||
parallel/test-tls-timeout-server.js
|
||||
parallel/test-tls-socket-destroy.js
|
||||
- handshakeTimeout is not implemented
|
||||
parallel/test-tls-retain-handle-no-abort.js
|
||||
- unable to verify the first certificate? UNABLE_TO_VERIFY_LEAF_SIGNATURE
|
||||
parallel/test-tls-client-resume.js
|
||||
- done https://github.com/oven-sh/bun/pull/20197
|
||||
parallel/test-tls-connect-timeout-option.js
|
||||
- support tls connect timeout option
|
||||
parallel/test-tls-getcertificate-x509.js
|
||||
- error: error:0900006e:PEM routines:OPENSSL_internal:NO_START_LINE
|
||||
parallel/test-tls-connect-given-socket.js
|
||||
- "invalid socket" when passing 'socket: socket' in tls.connect?
|
||||
parallel/test-double-tls-server.js
|
||||
- ALPNCallback
|
||||
parallel/test-tls-writewrap-leak.js
|
||||
- the write callback is supposed to get an error ECANCELED "Canceled because of SSL destruction"
|
||||
parallel/test-tls-client-default-ciphers.js
|
||||
parallel/test-tls-socket-constructor-alpn-options-parsing.js
|
||||
sequential/test-tls-session-timeout.js
|
||||
parallel/test-tls-env-extra-ca-with-options.js
|
||||
|
||||
# skipped (wontfix)
|
||||
|
||||
parallel/test-tls-no-sslv23.js
|
||||
- skipped
|
||||
|
||||
# wontfix
|
||||
|
||||
test-tls-disable-renegotiation.js
|
||||
- boringssl doesn't support client-initiated renegotiation
|
||||
|
||||
# passes already
|
||||
|
||||
parallel/test-tls-pause.js
|
||||
parallel/test-tls-connect-memleak.js
|
||||
- passes already
|
||||
|
||||
# Attempted
|
||||
|
||||
http.request errors because it passes port but no host and path as `localhost:${port}`. _http_client concatenates
|
||||
that to `localhost:${port}localhost:${port}` which is an invalid url
|
||||
- test-tls-over-http-tunnel.js
|
||||
- the problem is that sending an http request with path `abcd` will do `GET abcd HTTP/1.1`, but
|
||||
fetch `url.com/abcd` is `GET /abcd HTTP/1.1`. skipping the slash is invalid anyway and node's http server doesn't
|
||||
accept it. but net does.
|
||||
- http_client in bun is implemented with fetch which doesn't let you send a malformed http request
|
||||
- this might be unintentional? unclear
|
||||
|
||||
[ES] test-tls-disable-renegotiation.js:
|
||||
- missing ERR_INVALID_ARG_TYPE for client.renegotiate()
|
||||
- OpenSSL function should not have been called via OPENSSL_internal SSL routines
|
||||
- The error is emitted at: <https://github.com/google/boringssl/blob/035e720641f385e82c72b7b0a9e1d89e58cb5ed5/ssl/ssl_lib.cc#L1629>
|
||||
- marked as 'caller-initiated renegotiation is not supported'. you can't renegotiate unless a renegotiation is already pending.
|
||||
|
||||
test-tls-secure-session.js
|
||||
- client.on("session") never called?
|
||||
- probably because it sets secureProtocol: 'TLSv1_2_method'
|
||||
- we probably don't support setting secureProtocol
|
||||
- we don't emit a session event at all ever except in http2. node emits a session at the end of onConnectSecure and in onnewesssionclient
|
||||
- search terms: 'emit('session)'
|
||||
|
||||
# Skipped by electron
|
||||
|
||||
these tests are disabled by electron: (https://github.com/electron/electron/blob/main/script/node-disabled-tests.json)
|
||||
"parallel/test-tls-alpn-server-client",
|
||||
"parallel/test-tls-cli-min-version-1.0",
|
||||
"parallel/test-tls-cli-max-version-1.2",
|
||||
"parallel/test-tls-cli-max-version-1.3",
|
||||
"parallel/test-tls-cli-min-version-1.1",
|
||||
"parallel/test-tls-cli-min-version-1.2",
|
||||
"parallel/test-tls-cli-min-version-1.3",
|
||||
"parallel/test-tls-client-auth",
|
||||
"parallel/test-tls-client-getephemeralkeyinfo",
|
||||
"parallel/test-tls-client-mindhsize",
|
||||
"parallel/test-tls-client-reject",
|
||||
"parallel/test-tls-client-renegotiation-13",
|
||||
"parallel/test-tls-cnnic-whitelist",
|
||||
"parallel/test-tls-disable-renegotiation",
|
||||
"parallel/test-tls-empty-sni-context",
|
||||
"parallel/test-tls-error-stack",
|
||||
"parallel/test-tls-finished",
|
||||
"parallel/test-tls-generic-stream",
|
||||
"parallel/test-tls-getcipher",
|
||||
"parallel/test-tls-getprotocol",
|
||||
"parallel/test-tls-handshake-error",
|
||||
"parallel/test-tls-handshake-exception",
|
||||
"parallel/test-tls-hello-parser-failure",
|
||||
"parallel/test-tls-honorcipherorder",
|
||||
"parallel/test-tls-junk-closes-server",
|
||||
"parallel/test-tls-junk-server",
|
||||
"parallel/test-tls-key-mismatch",
|
||||
"parallel/test-tls-max-send-fragment",
|
||||
"parallel/test-tls-min-max-version",
|
||||
"parallel/test-tls-multi-key",
|
||||
"parallel/test-tls-multi-pfx",
|
||||
"parallel/test-tls-no-cert-required",
|
||||
"parallel/test-tls-options-boolean-check",
|
||||
"parallel/test-tls-passphrase",
|
||||
"parallel/test-tls-peer-certificate",
|
||||
"parallel/test-tls-pfx-authorizationerror",
|
||||
"parallel/test-tls-psk-circuit",
|
||||
"parallel/test-tls-reduced-SECLEVEL-in-cipher",
|
||||
"parallel/test-tls-root-certificates",
|
||||
"parallel/test-tls-server-failed-handshake-emits-clienterror",
|
||||
"parallel/test-tls-set-ciphers",
|
||||
"parallel/test-tls-set-ciphers-error",
|
||||
"parallel/test-tls-set-sigalgs",
|
||||
"parallel/test-tls-socket-allow-half-open-option",
|
||||
"parallel/test-tls-socket-failed-handshake-emits-error",
|
||||
"parallel/test-tls-ticket",
|
||||
"parallel/test-tls-ticket-cluster",
|
||||
17
test/js/node/test/fixtures/tls-check-extra-ca-certificates.js
vendored
Normal file
17
test/js/node/test/fixtures/tls-check-extra-ca-certificates.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const tls = require('tls');
|
||||
const assert = require('assert');
|
||||
|
||||
const defaultSet = new Set(tls.getCACertificates('default'));
|
||||
const extraSet = new Set(tls.getCACertificates('extra'));
|
||||
console.log(defaultSet.size, 'default certificates');
|
||||
console.log(extraSet.size, 'extra certificates')
|
||||
|
||||
// Parent process is supposed to call this with
|
||||
// NODE_EXTRA_CA_CERTS set to test/fixtures/keys/ca1-cert.pem.
|
||||
assert.strictEqual(extraSet.size, 1);
|
||||
|
||||
// Check that default set is a super set of extra set.
|
||||
assert.deepStrictEqual(defaultSet.intersection(extraSet),
|
||||
extraSet);
|
||||
58
test/js/node/test/parallel/test-double-tls-client.js
Normal file
58
test/js/node/test/parallel/test-double-tls-client.js
Normal file
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
|
||||
// In reality, this can be a HTTP CONNECT message, signaling the incoming
|
||||
// data is TLS encrypted
|
||||
const HEAD = 'XXXX';
|
||||
|
||||
const subserver = tls.createServer({
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
})
|
||||
.on('secureConnection', common.mustCall(() => {
|
||||
process.exit(0);
|
||||
}));
|
||||
|
||||
const server = tls.createServer({
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
})
|
||||
.listen(client)
|
||||
.on('secureConnection', (serverTlsSock) => {
|
||||
serverTlsSock.on('data', (chunk) => {
|
||||
assert.strictEqual(chunk.toString(), HEAD);
|
||||
subserver.emit('connection', serverTlsSock);
|
||||
});
|
||||
});
|
||||
|
||||
function client() {
|
||||
const down = tls.connect({
|
||||
host: '127.0.0.1',
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
}).on('secureConnect', () => {
|
||||
down.write(HEAD, common.mustSucceed());
|
||||
|
||||
// Sending tls data on a client TLSSocket with an active write led to a crash:
|
||||
//
|
||||
// node[16862]: ../src/crypto/crypto_tls.cc:963:virtual int node::crypto::TLSWrap::DoWrite(node::WriteWrap*,
|
||||
// uv_buf_t*, size_t, uv_stream_t*): Assertion `!current_write_' failed.
|
||||
// 1: 0xb090e0 node::Abort() [node]
|
||||
// 2: 0xb0915e [node]
|
||||
// 3: 0xca8413 node::crypto::TLSWrap::DoWrite(node::WriteWrap*, uv_buf_t*, unsigned long, uv_stream_s*) [node]
|
||||
// 4: 0xcaa549 node::StreamBase::Write(uv_buf_t*, unsigned long, uv_stream_s*, v8::Local<v8::Object>) [node]
|
||||
// 5: 0xca88d7 node::crypto::TLSWrap::EncOut() [node]
|
||||
// 6: 0xd3df3e [node]
|
||||
// 7: 0xd3f35f v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [node]
|
||||
// 8: 0x15d9ef9 [node]
|
||||
// Aborted
|
||||
tls.connect({
|
||||
socket: down,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
});
|
||||
}
|
||||
119
test/js/node/test/parallel/test-double-tls-server.js
Normal file
119
test/js/node/test/parallel/test-double-tls-server.js
Normal file
@@ -0,0 +1,119 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
|
||||
// Sending tls data on a server TLSSocket with an active write led to a crash:
|
||||
//
|
||||
// node[1296]: ../src/crypto/crypto_tls.cc:963:virtual int node::crypto::TLSWrap::DoWrite(node::WriteWrap*,
|
||||
// uv_buf_t*, size_t, uv_stream_t*): Assertion `!current_write_' failed.
|
||||
// 1: 0xb090e0 node::Abort() [node]
|
||||
// 2: 0xb0915e [node]
|
||||
// 3: 0xca8413 node::crypto::TLSWrap::DoWrite(node::WriteWrap*, uv_buf_t*, unsigned long, uv_stream_s*) [node]
|
||||
// 4: 0xcaa549 node::StreamBase::Write(uv_buf_t*, unsigned long, uv_stream_s*, v8::Local<v8::Object>) [node]
|
||||
// 5: 0xca88d7 node::crypto::TLSWrap::EncOut() [node]
|
||||
// 6: 0xca9ba8 node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) [node]
|
||||
// 7: 0xca8eb0 node::crypto::TLSWrap::ClearOut() [node]
|
||||
// 8: 0xca9ba0 node::crypto::TLSWrap::OnStreamRead(long, uv_buf_t const&) [node]
|
||||
// 9: 0xbe50dd node::LibuvStreamWrap::OnUvRead(long, uv_buf_t const*) [node]
|
||||
// 10: 0xbe54c4 [node]
|
||||
// 11: 0x15583d7 [node]
|
||||
// 12: 0x1558c00 [node]
|
||||
// 13: 0x155ede4 [node]
|
||||
// 14: 0x154d008 uv_run [node]
|
||||
|
||||
const serverReplaySize = 2 * 1024 * 1024;
|
||||
|
||||
(async function() {
|
||||
console.log('Starting test...');
|
||||
const tlsClientHello = await getClientHello();
|
||||
console.log('Got client hello, length:', tlsClientHello.length);
|
||||
|
||||
const subserver = tls.createServer({
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
ALPNCallback: common.mustCall(({ sn, protocols }) => {
|
||||
console.log('ALPN callback called with protocols:', protocols);
|
||||
// Once `subserver` receives `tlsClientHello` from the underlying net.Socket,
|
||||
// in this test, a TLSSocket actually, it should be able to proceed to the handshake
|
||||
// and emit this event
|
||||
assert.strictEqual(protocols[0], 'h2');
|
||||
return 'h2';
|
||||
}),
|
||||
});
|
||||
|
||||
const server = tls.createServer({
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
})
|
||||
.listen(startClient)
|
||||
.on('secureConnection', (serverTlsSock) => {
|
||||
console.log('Server received secure connection');
|
||||
// Craft writes that are large enough to stuck in sending
|
||||
// In reality this can be a 200 response to the incoming HTTP CONNECT
|
||||
const half = Buffer.alloc(serverReplaySize / 2, 0);
|
||||
console.log('Writing first half of data...');
|
||||
serverTlsSock.write(half, common.mustSucceed());
|
||||
console.log('Writing second half of data...');
|
||||
serverTlsSock.write(half, common.mustSucceed());
|
||||
|
||||
console.log('Emitting connection to subserver...');
|
||||
subserver.emit('connection', serverTlsSock);
|
||||
});
|
||||
|
||||
|
||||
function startClient() {
|
||||
console.log('Starting client connection...');
|
||||
const clientTlsSock = tls.connect({
|
||||
host: '127.0.0.1',
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
|
||||
const recv = [];
|
||||
let revcLen = 0;
|
||||
clientTlsSock.on('data', (chunk) => {
|
||||
console.log('Client received chunk of size:', chunk.length);
|
||||
revcLen += chunk.length;
|
||||
recv.push(chunk);
|
||||
if (revcLen > serverReplaySize) {
|
||||
console.log('Received enough data, checking server hello...');
|
||||
// Check the server's replay is followed by the subserver's TLS ServerHello
|
||||
const serverHelloFstByte = Buffer.concat(recv).subarray(serverReplaySize, serverReplaySize + 1);
|
||||
console.log('Server hello first byte:', serverHelloFstByte.toString('hex'));
|
||||
assert.strictEqual(serverHelloFstByte.toString('hex'), '16');
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
// In reality, one may want to send a HTTP CONNECT before starting this double TLS
|
||||
console.log('Writing client hello...');
|
||||
clientTlsSock.write(tlsClientHello);
|
||||
}
|
||||
})().then(common.mustCall());
|
||||
|
||||
function getClientHello() {
|
||||
return new Promise((resolve) => {
|
||||
console.log('Creating temporary server to get client hello...');
|
||||
const server = net.createServer((sock) => {
|
||||
console.log('Temporary server received connection');
|
||||
sock.on('data', (chunk) => {
|
||||
console.log('Temporary server received client hello, length:', chunk.length);
|
||||
resolve(chunk);
|
||||
});
|
||||
})
|
||||
.listen(() => {
|
||||
console.log('Temporary server listening, connecting client...');
|
||||
tls.connect({
|
||||
port: server.address().port,
|
||||
host: '127.0.0.1',
|
||||
ALPNProtocols: ['h2'],
|
||||
}).on('error', () => {
|
||||
console.log('Client connection error (expected)');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
49
test/js/node/test/parallel/test-gc-tls-external-memory.js
Normal file
49
test/js/node/test/parallel/test-gc-tls-external-memory.js
Normal file
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
// Flags: --expose-gc
|
||||
|
||||
// Tests that memoryUsage().external doesn't go negative
|
||||
// when a lot tls connections are opened and closed
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const { duplexPair } = require('stream');
|
||||
const { onGC } = require('../common/gc');
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
// Payload doesn't matter. We just need to have the tls
|
||||
// connection try and connect somewhere.
|
||||
const dummyPayload = Buffer.alloc(10000, 'yolo');
|
||||
|
||||
let runs = 0;
|
||||
|
||||
// Count garbage-collected TLS sockets.
|
||||
let gced = 0;
|
||||
function ongc() { gced++; }
|
||||
|
||||
connect();
|
||||
|
||||
function connect() {
|
||||
if (runs % 64 === 0)
|
||||
globalThis.gc();
|
||||
const externalMemoryUsage = process.memoryUsage().external;
|
||||
assert(externalMemoryUsage >= 0, `${externalMemoryUsage} < 0`);
|
||||
if (runs++ === 512) {
|
||||
// Make sure at least half the TLS sockets have been garbage collected
|
||||
// (so that this test can actually check what it's testing):
|
||||
assert(gced >= 256, `${gced} < 256`);
|
||||
return;
|
||||
}
|
||||
|
||||
const [ clientSide, serverSide ] = duplexPair();
|
||||
|
||||
const tlsSocket = tls.connect({ socket: clientSide });
|
||||
tlsSocket.on('error', common.mustCall(connect));
|
||||
onGC(tlsSocket, { ongc });
|
||||
|
||||
// Use setImmediate so that we don't trigger the error within the same
|
||||
// event loop tick.
|
||||
setImmediate(() => serverSide.write(dummyPayload));
|
||||
}
|
||||
49
test/js/node/test/parallel/test-tls-addca.js
Normal file
49
test/js/node/test/parallel/test-tls-addca.js
Normal file
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// Adding a CA certificate to contextWithCert should not also add it to
|
||||
// contextWithoutCert. This is tested by trying to connect to a server that
|
||||
// depends on that CA using contextWithoutCert.
|
||||
|
||||
const {
|
||||
assert, connect, keys, tls
|
||||
} = require(fixtures.path('tls-connect'));
|
||||
|
||||
const contextWithoutCert = tls.createSecureContext({});
|
||||
const contextWithCert = tls.createSecureContext({});
|
||||
contextWithCert.context.addCACert(keys.agent1.ca);
|
||||
|
||||
const serverOptions = {
|
||||
key: keys.agent1.key,
|
||||
cert: keys.agent1.cert,
|
||||
};
|
||||
|
||||
const clientOptions = {
|
||||
ca: [keys.agent1.ca],
|
||||
servername: 'agent1',
|
||||
rejectUnauthorized: true,
|
||||
};
|
||||
|
||||
// This client should fail to connect because it doesn't trust the CA
|
||||
// certificate.
|
||||
clientOptions.secureContext = contextWithoutCert;
|
||||
|
||||
connect({
|
||||
client: clientOptions,
|
||||
server: serverOptions,
|
||||
}, common.mustCall((err, pair, cleanup) => {
|
||||
assert(err);
|
||||
assert.strictEqual(err.message, 'unable to verify the first certificate');
|
||||
cleanup();
|
||||
|
||||
// This time it should connect because contextWithCert includes the needed CA
|
||||
// certificate.
|
||||
clientOptions.secureContext = contextWithCert;
|
||||
connect({
|
||||
client: clientOptions,
|
||||
server: serverOptions,
|
||||
}, common.mustSucceed((pair, cleanup) => {
|
||||
cleanup();
|
||||
}));
|
||||
}));
|
||||
149
test/js/node/test/parallel/test-tls-basic-validations.js
Normal file
149
test/js/node/test/parallel/test-tls-basic-validations.js
Normal file
@@ -0,0 +1,149 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
// TODO:
|
||||
// assert.throws(
|
||||
// () => tls.createSecureContext({ ciphers: 1 }),
|
||||
// {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// message: 'The "options.ciphers" property must be of type string.' +
|
||||
// ' Received type number (1)'
|
||||
// });
|
||||
|
||||
assert.throws(
|
||||
() => tls.createServer({ ciphers: 1 }),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: 'The "options.ciphers" property must be of type string.' +
|
||||
' Received type number (1)'
|
||||
});
|
||||
|
||||
// TODO:
|
||||
// assert.throws(
|
||||
// () => tls.createSecureContext({ key: 'dummykey', passphrase: 1 }),
|
||||
// {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// message: /The "options\.passphrase" property must be of type string/
|
||||
// });
|
||||
|
||||
assert.throws(
|
||||
() => tls.createServer({ key: 'dummykey', passphrase: 1 }),
|
||||
{
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
message: /The "options\.passphrase" property must be of type string/
|
||||
});
|
||||
|
||||
// TODO:
|
||||
// assert.throws(
|
||||
// () => tls.createServer({ ecdhCurve: 1 }),
|
||||
// {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// message: /The "options\.ecdhCurve" property must be of type string/
|
||||
// });
|
||||
|
||||
// TODO:
|
||||
// assert.throws(
|
||||
// () => tls.createServer({ handshakeTimeout: 'abcd' }),
|
||||
// {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// message: 'The "options.handshakeTimeout" property must be of type number.' +
|
||||
// " Received type string ('abcd')"
|
||||
// }
|
||||
// );
|
||||
|
||||
// TODO:
|
||||
// assert.throws(
|
||||
// () => tls.createServer({ sessionTimeout: 'abcd' }),
|
||||
// {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// message: /The "options\.sessionTimeout" property must be of type number/
|
||||
// });
|
||||
|
||||
// TODO:
|
||||
// assert.throws(
|
||||
// () => tls.createServer({ ticketKeys: 'abcd' }),
|
||||
// {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// message: /The "options\.ticketKeys" property must be an instance of/
|
||||
// });
|
||||
|
||||
// TODO:
|
||||
// assert.throws(() => tls.createServer({ ticketKeys: Buffer.alloc(0) }), {
|
||||
// code: 'ERR_INVALID_ARG_VALUE',
|
||||
// message: /The property 'options\.ticketKeys' must be exactly 48 bytes/
|
||||
// });
|
||||
|
||||
{
|
||||
const buffer = Buffer.from('abcd');
|
||||
const out = {};
|
||||
tls.convertALPNProtocols(buffer, out);
|
||||
out.ALPNProtocols.write('efgh');
|
||||
assert(buffer.equals(Buffer.from('abcd')));
|
||||
assert(out.ALPNProtocols.equals(Buffer.from('efgh')));
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// {
|
||||
// const arrayBufferViewStr = 'abcd';
|
||||
// const inputBuffer = Buffer.from(arrayBufferViewStr.repeat(8), 'utf8');
|
||||
// for (const expectView of common.getArrayBufferViews(inputBuffer)) {
|
||||
// const out = {};
|
||||
// const expected = Buffer.from(expectView.buffer.slice(),
|
||||
// expectView.byteOffset,
|
||||
// expectView.byteLength);
|
||||
// tls.convertALPNProtocols(expectView, out);
|
||||
// assert(out.ALPNProtocols.equals(expected));
|
||||
// }
|
||||
// }
|
||||
|
||||
// TODO:
|
||||
// {
|
||||
// const protocols = [(new String('a')).repeat(500)];
|
||||
// const out = {};
|
||||
// assert.throws(
|
||||
// () => tls.convertALPNProtocols(protocols, out),
|
||||
// {
|
||||
// code: 'ERR_OUT_OF_RANGE',
|
||||
// message: 'The byte length of the protocol at index 0 exceeds the ' +
|
||||
// 'maximum length. It must be <= 255. Received 500'
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
// TODO:
|
||||
// assert.throws(() => { tls.createSecureContext({ minVersion: 'fhqwhgads' }); },
|
||||
// {
|
||||
// code: 'ERR_TLS_INVALID_PROTOCOL_VERSION',
|
||||
// name: 'TypeError'
|
||||
// });
|
||||
|
||||
// TODO:
|
||||
// assert.throws(() => { tls.createSecureContext({ maxVersion: 'fhqwhgads' }); },
|
||||
// {
|
||||
// code: 'ERR_TLS_INVALID_PROTOCOL_VERSION',
|
||||
// name: 'TypeError'
|
||||
// });
|
||||
|
||||
// TODO:
|
||||
// for (const checkServerIdentity of [undefined, null, 1, true]) {
|
||||
// assert.throws(() => {
|
||||
// tls.connect({ checkServerIdentity });
|
||||
// }, {
|
||||
// code: 'ERR_INVALID_ARG_TYPE',
|
||||
// name: 'TypeError',
|
||||
// });
|
||||
// }
|
||||
43
test/js/node/test/parallel/test-tls-buffersize.js
Normal file
43
test/js/node/test/parallel/test-tls-buffersize.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
|
||||
const iter = 10;
|
||||
|
||||
const server = tls.createServer({
|
||||
key: fixtures.readKey('agent2-key.pem'),
|
||||
cert: fixtures.readKey('agent2-cert.pem')
|
||||
}, common.mustCall((socket) => {
|
||||
let str = '';
|
||||
socket.setEncoding('utf-8');
|
||||
socket.on('data', (chunk) => { str += chunk; });
|
||||
|
||||
socket.on('end', common.mustCall(() => {
|
||||
assert.strictEqual(str, 'a'.repeat(iter - 1));
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const client = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(() => {
|
||||
assert.strictEqual(client.bufferSize, 0);
|
||||
|
||||
for (let i = 1; i < iter; i++) {
|
||||
client.write('a');
|
||||
assert.strictEqual(client.bufferSize, i);
|
||||
}
|
||||
|
||||
client.on('finish', common.mustCall(() => {
|
||||
assert.strictEqual(client.bufferSize, 0);
|
||||
}));
|
||||
|
||||
client.end();
|
||||
}));
|
||||
}));
|
||||
59
test/js/node/test/parallel/test-tls-cert-chains-concat.js
Normal file
59
test/js/node/test/parallel/test-tls-cert-chains-concat.js
Normal file
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// Check cert chain is received by client, and is completed with the ca cert
|
||||
// known to the client.
|
||||
|
||||
const {
|
||||
assert, connect, debug, keys
|
||||
} = require(fixtures.path('tls-connect'));
|
||||
|
||||
console.log('Starting TLS cert chain test...');
|
||||
|
||||
// agent6-cert.pem includes cert for agent6 and ca3
|
||||
connect({
|
||||
client: {
|
||||
checkServerIdentity: (servername, cert) => {
|
||||
console.log('checkServerIdentity called with:', { servername, cert });
|
||||
},
|
||||
ca: keys.agent6.ca,
|
||||
},
|
||||
server: {
|
||||
cert: keys.agent6.cert,
|
||||
key: keys.agent6.key,
|
||||
},
|
||||
}, common.mustSucceed((pair, cleanup) => {
|
||||
console.log('TLS connection established');
|
||||
|
||||
const peer = pair.client.conn.getPeerCertificate();
|
||||
console.log('Peer certificate:', peer);
|
||||
debug('peer:\n', peer);
|
||||
assert.strictEqual(peer.subject.emailAddress, 'adam.lippai@tresorit.com');
|
||||
assert.strictEqual(peer.subject.CN, 'Ádám Lippai');
|
||||
assert.strictEqual(peer.issuer.CN, 'ca3');
|
||||
assert.match(peer.serialNumber, /5B75D77EDC7FB5B7FA9F1424DA4C64FB815DCBDE/i);
|
||||
|
||||
const next = pair.client.conn.getPeerCertificate(true).issuerCertificate;
|
||||
console.log('Next certificate in chain:', next);
|
||||
const root = next.issuerCertificate;
|
||||
delete next.issuerCertificate;
|
||||
debug('next:\n', next);
|
||||
assert.strictEqual(next.subject.CN, 'ca3');
|
||||
assert.strictEqual(next.issuer.CN, 'ca1');
|
||||
assert.match(next.serialNumber, /147D36C1C2F74206DE9FAB5F2226D78ADB00A425/i);
|
||||
|
||||
console.log('Root certificate:', root);
|
||||
debug('root:\n', root);
|
||||
assert.strictEqual(root.subject.CN, 'ca1');
|
||||
assert.strictEqual(root.issuer.CN, 'ca1');
|
||||
assert.match(root.serialNumber, /4AB16C8DFD6A7D0D2DFCABDF9C4B0E92C6AD0229/i);
|
||||
|
||||
// No client cert, so empty object returned.
|
||||
console.log('Server peer certificate:', pair.server.conn.getPeerCertificate());
|
||||
assert.deepStrictEqual(pair.server.conn.getPeerCertificate(), {});
|
||||
assert.deepStrictEqual(pair.server.conn.getPeerCertificate(true), {});
|
||||
|
||||
console.log('Test completed successfully');
|
||||
return cleanup();
|
||||
}));
|
||||
14
test/js/node/test/parallel/test-tls-cli-min-max-conflict.js
Normal file
14
test/js/node/test/parallel/test-tls-cli-min-max-conflict.js
Normal file
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
// Check that conflicting TLS protocol versions are not allowed
|
||||
|
||||
const assert = require('assert');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const args = ['--tls-min-v1.3', '--tls-max-v1.2', '-p', 'process.version'];
|
||||
child_process.execFile(process.argv[0], args, (err) => {
|
||||
assert(err);
|
||||
assert.match(err.message, /not both/);
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) { common.skip('missing crypto'); };
|
||||
|
||||
const assert = require('assert');
|
||||
const { once } = require('events');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// agent6-cert.pem is signed by intermediate cert of ca3.
|
||||
// The server has a cert chain of agent6->ca3->ca1(root).
|
||||
|
||||
const { it, beforeEach, afterEach, describe } = require('node:test');
|
||||
|
||||
describe('allowPartialTrustChain', { skip: !common.hasCrypto }, function() {
|
||||
const tls = require('tls');
|
||||
let server;
|
||||
let client;
|
||||
let opts;
|
||||
|
||||
beforeEach(async function() {
|
||||
console.log('Setting up server and options...');
|
||||
server = tls.createServer({
|
||||
ca: fixtures.readKey('ca3-cert.pem'),
|
||||
key: fixtures.readKey('agent6-key.pem'),
|
||||
cert: fixtures.readKey('agent6-cert.pem'),
|
||||
}, (socket) => socket.resume());
|
||||
server.listen(0);
|
||||
await once(server, 'listening');
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
|
||||
opts = {
|
||||
port: server.address().port,
|
||||
ca: fixtures.readKey('ca3-cert.pem'),
|
||||
checkServerIdentity() {}
|
||||
};
|
||||
console.log('Options configured:', opts);
|
||||
});
|
||||
|
||||
afterEach(async function() {
|
||||
console.log('Cleaning up client and server...');
|
||||
client?.destroy();
|
||||
server?.close();
|
||||
});
|
||||
|
||||
it('can connect successfully with allowPartialTrustChain: true', async function() {
|
||||
console.log('Testing connection with allowPartialTrustChain: true');
|
||||
client = tls.connect({ ...opts, allowPartialTrustChain: true });
|
||||
await once(client, 'secureConnect'); // Should not throw
|
||||
console.log('Successfully connected with allowPartialTrustChain: true');
|
||||
});
|
||||
|
||||
it('fails without with allowPartialTrustChain: true for an intermediate cert in the CA', async function() {
|
||||
console.log('Testing connection without allowPartialTrustChain');
|
||||
// Consistency check: Connecting fails without allowPartialTrustChain: true
|
||||
await assert.rejects(async () => {
|
||||
console.log('Attempting connection without allowPartialTrustChain...');
|
||||
const client = tls.connect(opts);
|
||||
await once(client, 'secureConnect');
|
||||
}, { code: 'UNABLE_TO_GET_ISSUER_CERT' });
|
||||
console.log('Connection failed as expected without allowPartialTrustChain');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
function Done() {}
|
||||
|
||||
function test1() {
|
||||
let ciphers = '';
|
||||
|
||||
tls.createSecureContext = function(options) {
|
||||
ciphers = options.ciphers;
|
||||
throw new Done();
|
||||
};
|
||||
|
||||
assert.throws(tls.connect, Done);
|
||||
|
||||
assert.strictEqual(ciphers, tls.DEFAULT_CIPHERS);
|
||||
}
|
||||
test1();
|
||||
132
test/js/node/test/parallel/test-tls-client-resume.js
Normal file
132
test/js/node/test/parallel/test-tls-client-resume.js
Normal file
@@ -0,0 +1,132 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
|
||||
// Check that the ticket from the first connection causes session resumption
|
||||
// when used to make a second connection.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
console.log('Starting TLS client resume test');
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent2-key.pem'),
|
||||
cert: fixtures.readKey('agent2-cert.pem')
|
||||
};
|
||||
|
||||
console.log('Server options:', options);
|
||||
|
||||
// create server
|
||||
const server = tls.Server(options, common.mustCall((socket) => {
|
||||
console.log('Server received connection');
|
||||
socket.end('Goodbye');
|
||||
}, 2));
|
||||
|
||||
// start listening
|
||||
server.listen(0, common.mustCall(function() {
|
||||
console.log('Server listening on port:', this.address().port);
|
||||
let sessionx = null; // From right after connect, invalid for TLS1.3
|
||||
let session1 = null; // Delivered by the session event, always valid.
|
||||
let sessions = 0;
|
||||
let tls13;
|
||||
const client1 = tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(() => {
|
||||
console.log('Client1 connected');
|
||||
tls13 = client1.getProtocol() === 'TLSv1.3';
|
||||
console.log('TLS version:', client1.getProtocol());
|
||||
assert.strictEqual(client1.isSessionReused(), false);
|
||||
sessionx = client1.getSession();
|
||||
console.log('SessionX obtained:', !!sessionx);
|
||||
assert(sessionx);
|
||||
|
||||
if (session1)
|
||||
reconnect();
|
||||
}));
|
||||
|
||||
client1.on('data', common.mustCall((data) => {
|
||||
console.log('Client1 received data:', data.toString());
|
||||
}));
|
||||
|
||||
client1.once('session', common.mustCall((session) => {
|
||||
console.log('Session1 event received');
|
||||
session1 = session;
|
||||
console.log('Session1 obtained:', !!session1);
|
||||
assert(session1);
|
||||
if (sessionx)
|
||||
reconnect();
|
||||
}));
|
||||
|
||||
client1.on('session', () => {
|
||||
console.log('Client1 session event #', ++sessions);
|
||||
});
|
||||
|
||||
client1.on('close', () => {
|
||||
console.log('Client1 closed');
|
||||
assert.strictEqual(sessions, tls13 ? 2 : 1);
|
||||
});
|
||||
|
||||
function reconnect() {
|
||||
console.log('Starting reconnect');
|
||||
assert(sessionx);
|
||||
assert(session1);
|
||||
if (tls13) {
|
||||
console.log('TLS1.3 session comparison');
|
||||
// For TLS1.3, the session immediately after handshake is a dummy,
|
||||
// unresumable session. The one delivered later in session event is
|
||||
// resumable.
|
||||
assert.notStrictEqual(sessionx.compare(session1), 0);
|
||||
} else {
|
||||
console.log('TLS1.2 session comparison');
|
||||
// For TLS1.2, they are identical.
|
||||
assert.strictEqual(sessionx.compare(session1), 0);
|
||||
}
|
||||
|
||||
const opts = {
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false,
|
||||
session: session1,
|
||||
};
|
||||
|
||||
console.log('Connecting client2 with session');
|
||||
const client2 = tls.connect(opts, common.mustCall(() => {
|
||||
console.log('Client2 connected');
|
||||
assert.strictEqual(client2.isSessionReused(), true);
|
||||
}));
|
||||
|
||||
client2.on('close', common.mustCall(() => {
|
||||
console.log('Client2 closed');
|
||||
server.close();
|
||||
}));
|
||||
|
||||
client2.resume();
|
||||
}
|
||||
|
||||
client1.resume();
|
||||
}));
|
||||
@@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
{
|
||||
assert.throws(
|
||||
() => { tls.createSecureContext({ clientCertEngine: 0 }); },
|
||||
{ code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: / Received type number \(0\)/ });
|
||||
}
|
||||
56
test/js/node/test/parallel/test-tls-cnnic-whitelist.js
Normal file
56
test/js/node/test/parallel/test-tls-cnnic-whitelist.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// Flags: --use-bundled-ca
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
function loadPEM(n) {
|
||||
return fixtures.readKey(`${n}.pem`);
|
||||
}
|
||||
|
||||
const testCases = [
|
||||
// Test 1: for the fix of node#2061
|
||||
// agent6-cert.pem is signed by intermediate cert of ca3.
|
||||
// The server has a cert chain of agent6->ca3->ca1(root) but
|
||||
// tls.connect should be failed with an error of
|
||||
// UNABLE_TO_GET_ISSUER_CERT_LOCALLY since the root CA of ca1 is not
|
||||
// installed locally.
|
||||
{
|
||||
serverOpts: {
|
||||
ca: loadPEM('ca3-key'),
|
||||
key: loadPEM('agent6-key'),
|
||||
cert: loadPEM('agent6-cert')
|
||||
},
|
||||
clientOpts: {
|
||||
port: undefined,
|
||||
rejectUnauthorized: true
|
||||
},
|
||||
errorCode: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY'
|
||||
},
|
||||
];
|
||||
|
||||
function runTest(tindex) {
|
||||
const tcase = testCases[tindex];
|
||||
|
||||
if (!tcase) return;
|
||||
|
||||
const server = tls.createServer(tcase.serverOpts, (s) => {
|
||||
s.resume();
|
||||
}).listen(0, common.mustCall(function() {
|
||||
tcase.clientOpts.port = this.address().port;
|
||||
const client = tls.connect(tcase.clientOpts);
|
||||
client.on('error', common.mustCall((e) => {
|
||||
assert.strictEqual(e.code, tcase.errorCode);
|
||||
server.close(common.mustCall(() => {
|
||||
runTest(tindex + 1);
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
runTest(0);
|
||||
@@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
// This test verifies that `tls.connect()` honors the `allowHalfOpen` option.
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
|
||||
{
|
||||
const socket = tls.connect({ port: 42, lookup() {} });
|
||||
console.log('Default allowHalfOpen:', socket.allowHalfOpen);
|
||||
assert.strictEqual(socket.allowHalfOpen, false);
|
||||
}
|
||||
|
||||
{
|
||||
const socket = tls.connect({ port: 42, allowHalfOpen: false, lookup() {} });
|
||||
console.log('Explicit allowHalfOpen=false:', socket.allowHalfOpen);
|
||||
assert.strictEqual(socket.allowHalfOpen, false);
|
||||
}
|
||||
|
||||
const server = tls.createServer({
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
}, common.mustCall((socket) => {
|
||||
console.log('Server: New connection received');
|
||||
server.close();
|
||||
|
||||
let message = '';
|
||||
|
||||
socket.setEncoding('utf8');
|
||||
socket.on('data', (chunk) => {
|
||||
console.log('Server received:', chunk);
|
||||
message += chunk;
|
||||
|
||||
if (message === 'Hello') {
|
||||
console.log('Server sending response');
|
||||
socket.end(message);
|
||||
message = '';
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('end', common.mustCall(() => {
|
||||
console.log('Server received end, final message:', message);
|
||||
assert.strictEqual(message, 'Bye');
|
||||
}));
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
const socket = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false,
|
||||
allowHalfOpen: true,
|
||||
}, common.mustCall(() => {
|
||||
console.log('Client connected');
|
||||
let message = '';
|
||||
|
||||
socket.on('data', (chunk) => {
|
||||
console.log('Client received:', chunk);
|
||||
message += chunk;
|
||||
});
|
||||
|
||||
socket.on('end', common.mustCall(() => {
|
||||
console.log('Client received end, message:', message);
|
||||
assert.strictEqual(message, 'Hello');
|
||||
|
||||
setTimeout(() => {
|
||||
console.log('Client writing final message');
|
||||
assert(socket.writable);
|
||||
assert(socket.write('Bye'));
|
||||
// socket.end();
|
||||
}, 50);
|
||||
}));
|
||||
|
||||
console.log('Client writing initial message');
|
||||
socket.write('Hello');
|
||||
}));
|
||||
|
||||
socket.setEncoding('utf8');
|
||||
}));
|
||||
103
test/js/node/test/parallel/test-tls-connect-given-socket.js
Normal file
103
test/js/node/test/parallel/test-tls-connect-given-socket.js
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
|
||||
console.log('Loading certificates...');
|
||||
const options = {
|
||||
key: fixtures.readKey('rsa_private.pem'),
|
||||
cert: fixtures.readKey('rsa_cert.crt')
|
||||
};
|
||||
console.log('Certificates loaded successfully');
|
||||
|
||||
const server = tls.createServer(options, common.mustCall((socket) => {
|
||||
console.log('Server received connection');
|
||||
socket.end('Hello');
|
||||
}, 2)).listen(0, common.mustCall(() => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
let waiting = 2;
|
||||
function establish(socket, calls) {
|
||||
console.log('Establishing TLS connection with socket');
|
||||
const client = tls.connect({
|
||||
rejectUnauthorized: false,
|
||||
socket: socket
|
||||
}, common.mustCall(() => {
|
||||
console.log('TLS connection established');
|
||||
let data = '';
|
||||
client.on('data', common.mustCall((chunk) => {
|
||||
console.log('Client received data chunk');
|
||||
data += chunk.toString();
|
||||
}));
|
||||
client.on('end', common.mustCall(() => {
|
||||
console.log('Client connection ended');
|
||||
assert.strictEqual(data, 'Hello');
|
||||
if (--waiting === 0) {
|
||||
console.log('All connections completed, closing server');
|
||||
server.close();
|
||||
}
|
||||
}));
|
||||
}, calls));
|
||||
assert(client.readable);
|
||||
assert(client.writable);
|
||||
console.log('Client socket is readable and writable');
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
const { port } = server.address();
|
||||
|
||||
// Immediate death socket
|
||||
console.log('Creating immediate death socket');
|
||||
const immediateDeath = net.connect(port);
|
||||
establish(immediateDeath, 0).destroy();
|
||||
console.log('Immediate death socket destroyed');
|
||||
|
||||
// Outliving
|
||||
console.log('Creating outliving TCP connection');
|
||||
const outlivingTCP = net.connect(port, common.mustCall(() => {
|
||||
console.log('Outliving TCP connected, destroying TLS');
|
||||
outlivingTLS.destroy();
|
||||
next();
|
||||
}));
|
||||
const outlivingTLS = establish(outlivingTCP, 0);
|
||||
|
||||
function next() {
|
||||
console.log('Starting next connection phase');
|
||||
// Already connected socket
|
||||
const connected = net.connect(port, common.mustCall(() => {
|
||||
console.log('Connected socket ready, establishing TLS');
|
||||
establish(connected);
|
||||
}));
|
||||
|
||||
// Connecting socket
|
||||
console.log('Creating connecting socket');
|
||||
const connecting = net.connect(port);
|
||||
establish(connecting);
|
||||
}
|
||||
}));
|
||||
66
test/js/node/test/parallel/test-tls-connect-memleak.js
Normal file
66
test/js/node/test/parallel/test-tls-connect-memleak.js
Normal file
@@ -0,0 +1,66 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
// Flags: --expose-gc
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const { onGC } = require('../common/gc');
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// Test that the implicit listener for an 'connect' event on tls.Sockets is
|
||||
// added using `once()`, i.e. can be gc'ed once that event has occurred.
|
||||
|
||||
const server = tls.createServer({
|
||||
cert: fixtures.readKey('rsa_cert.crt'),
|
||||
key: fixtures.readKey('rsa_private.pem')
|
||||
}).listen(0);
|
||||
|
||||
let collected = false;
|
||||
const gcListener = { ongc() { collected = true; } };
|
||||
|
||||
{
|
||||
const gcObject = {};
|
||||
onGC(gcObject, gcListener);
|
||||
|
||||
const sock = tls.connect(
|
||||
server.address().port,
|
||||
{ rejectUnauthorized: false },
|
||||
common.mustCall(() => {
|
||||
assert.strictEqual(gcObject, gcObject); // Keep reference alive
|
||||
assert.strictEqual(collected, false);
|
||||
setImmediate(done, sock);
|
||||
}));
|
||||
}
|
||||
|
||||
function done(sock) {
|
||||
globalThis.gc();
|
||||
setImmediate(() => {
|
||||
assert.strictEqual(collected, true);
|
||||
sock.end();
|
||||
server.close();
|
||||
});
|
||||
}
|
||||
65
test/js/node/test/parallel/test-tls-connect-stream-writes.js
Normal file
65
test/js/node/test/parallel/test-tls-connect-stream-writes.js
Normal file
@@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const stream = require('stream');
|
||||
const net = require('net');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const options = { key: fixtures.readKey('rsa_private.pem'),
|
||||
cert: fixtures.readKey('rsa_cert.crt'),
|
||||
ca: [ fixtures.readKey('rsa_ca.crt') ],
|
||||
ciphers: 'AES256-GCM-SHA384' };
|
||||
const content = 'hello world';
|
||||
const recv_bufs = [];
|
||||
let send_data = '';
|
||||
const server = tls.createServer(options, function(s) {
|
||||
s.on('data', function(c) {
|
||||
recv_bufs.push(c);
|
||||
});
|
||||
});
|
||||
server.listen(0, function() {
|
||||
const raw = net.connect(this.address().port);
|
||||
|
||||
let pending = false;
|
||||
raw.on('readable', function() {
|
||||
if (pending)
|
||||
p._read();
|
||||
});
|
||||
|
||||
const p = new stream.Duplex({
|
||||
read: function read() {
|
||||
pending = false;
|
||||
|
||||
const chunk = raw.read();
|
||||
if (chunk) {
|
||||
this.push(chunk);
|
||||
} else {
|
||||
pending = true;
|
||||
}
|
||||
},
|
||||
write: function write(data, enc, cb) {
|
||||
raw.write(data, enc, cb);
|
||||
}
|
||||
});
|
||||
|
||||
const socket = tls.connect({
|
||||
socket: p,
|
||||
rejectUnauthorized: false
|
||||
}, function() {
|
||||
for (let i = 0; i < 50; ++i) {
|
||||
socket.write(content);
|
||||
send_data += content;
|
||||
}
|
||||
socket.end();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
const recv_data = (Buffer.concat(recv_bufs)).toString();
|
||||
assert.strictEqual(send_data, recv_data);
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
// This test verifies that `tls.connect()` honors the `timeout` option when the
|
||||
// socket is internally created.
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
console.log('Creating TLS socket with timeout option...');
|
||||
const socket = tls.connect({
|
||||
port: 42,
|
||||
lookup: () => {},
|
||||
timeout: 1000
|
||||
});
|
||||
|
||||
console.log('Socket timeout value:', socket.timeout);
|
||||
assert.strictEqual(socket.timeout, 1000);
|
||||
console.log('Timeout assertion passed');
|
||||
36
test/js/node/test/parallel/test-tls-delayed-attach-error.js
Normal file
36
test/js/node/test/parallel/test-tls-delayed-attach-error.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const bonkers = Buffer.alloc(1024, 42);
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem')
|
||||
};
|
||||
|
||||
const server = net.createServer(common.mustCall(function(c) {
|
||||
setTimeout(common.mustCall(function() {
|
||||
const s = new tls.TLSSocket(c, {
|
||||
isServer: true,
|
||||
secureContext: tls.createSecureContext(options)
|
||||
});
|
||||
|
||||
s.on('_tlsError', common.mustCall());
|
||||
|
||||
s.on('close', function() {
|
||||
server.close();
|
||||
s.destroy();
|
||||
});
|
||||
}), 200);
|
||||
})).listen(0, function() {
|
||||
const c = net.connect({ port: this.address().port }, function() {
|
||||
c.write(bonkers);
|
||||
});
|
||||
});
|
||||
13
test/js/node/test/parallel/test-tls-destroy-stream-12.js
Normal file
13
test/js/node/test/parallel/test-tls-destroy-stream-12.js
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
// test-tls-destroy-stream specifically for TLS1.2.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
|
||||
tls.DEFAULT_MAX_VERSION = 'TLSv1.2';
|
||||
|
||||
require('./test-tls-destroy-stream.js');
|
||||
104
test/js/node/test/parallel/test-tls-destroy-stream.js
Normal file
104
test/js/node/test/parallel/test-tls-destroy-stream.js
Normal file
@@ -0,0 +1,104 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { duplexPair } = require('stream');
|
||||
const net = require('net');
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
console.log('Starting TLS destroy stream test...');
|
||||
|
||||
tls.DEFAULT_MAX_VERSION = 'TLSv1.3';
|
||||
|
||||
// This test ensures that an instance of StreamWrap should emit "end" and
|
||||
// "close" when the socket on the other side call `destroy()` instead of
|
||||
// `end()`.
|
||||
// Refs: https://github.com/nodejs/node/issues/14605
|
||||
const CONTENT = 'Hello World';
|
||||
const tlsServer = tls.createServer(
|
||||
{
|
||||
key: fixtures.readKey('rsa_private.pem'),
|
||||
cert: fixtures.readKey('rsa_cert.crt'),
|
||||
ca: [fixtures.readKey('rsa_ca.crt')],
|
||||
},
|
||||
(socket) => {
|
||||
console.log('TLS server received connection');
|
||||
socket.on('close', common.mustCall(() => {
|
||||
console.log('TLS server socket closed');
|
||||
}));
|
||||
console.log('Writing content to socket:', CONTENT);
|
||||
socket.write(CONTENT);
|
||||
console.log('Destroying socket');
|
||||
socket.destroy();
|
||||
|
||||
socket.on('error', (err) => {
|
||||
console.log('Socket error:', err.code);
|
||||
// destroy() is sync, write() is async, whether write completes depends
|
||||
// on the protocol, it is not guaranteed by stream API.
|
||||
if (err.code === 'ERR_STREAM_DESTROYED')
|
||||
return;
|
||||
assert.ifError(err);
|
||||
});
|
||||
},
|
||||
);
|
||||
tlsServer.on('connection', () => {
|
||||
console.log('TLS server connection event');
|
||||
})
|
||||
|
||||
const server = net.createServer((conn) => {
|
||||
console.log('Net server received connection');
|
||||
conn.on('error', common.mustNotCall());
|
||||
// Assume that we want to use data to determine what to do with connections.
|
||||
conn.once('data', common.mustCall((chunk) => {
|
||||
console.log('Received initial data chunk');
|
||||
const [ clientSide, serverSide ] = duplexPair();
|
||||
serverSide.on('close', common.mustCall(() => {
|
||||
console.log('Server side closed, destroying connection');
|
||||
conn.destroy();
|
||||
}));
|
||||
clientSide.pipe(conn);
|
||||
conn.pipe(clientSide);
|
||||
|
||||
conn.on('close', common.mustCall(() => {
|
||||
console.log('Connection closed, destroying client side');
|
||||
clientSide.destroy();
|
||||
}));
|
||||
clientSide.on('close', common.mustCall(() => {
|
||||
console.log('Client side closed, destroying connection');
|
||||
conn.destroy();
|
||||
}));
|
||||
|
||||
process.nextTick(() => {
|
||||
console.log('Unshifting chunk');
|
||||
conn.unshift(chunk);
|
||||
});
|
||||
|
||||
console.log('Emitting connection to TLS server');
|
||||
tlsServer.emit('connection', serverSide);
|
||||
}));
|
||||
});
|
||||
server.on('connection', () => {
|
||||
console.log('Net server connection event');
|
||||
})
|
||||
|
||||
server.listen(0, () => {
|
||||
const port = server.address().port;
|
||||
console.log('Server listening on port:', port);
|
||||
const conn = tls.connect({ port, rejectUnauthorized: false }, () => {
|
||||
console.log('TLS client connected');
|
||||
// Whether the server's write() completed before its destroy() is
|
||||
// indeterminate, but if data was written, we should receive it correctly.
|
||||
conn.on('data', (data) => {
|
||||
console.log('Client received data:', data.toString('utf8'));
|
||||
assert.strictEqual(data.toString('utf8'), CONTENT);
|
||||
});
|
||||
conn.on('error', common.mustNotCall());
|
||||
conn.on('close', common.mustCall(() => {
|
||||
console.log('Client closed, closing server');
|
||||
server.close();
|
||||
}));
|
||||
});
|
||||
});
|
||||
108
test/js/node/test/parallel/test-tls-disable-renegotiation.js
Normal file
108
test/js/node/test/parallel/test-tls-disable-renegotiation.js
Normal file
@@ -0,0 +1,108 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// Tests that calling disableRenegotiation on a TLSSocket stops renegotiation.
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
|
||||
// Renegotiation as a protocol feature was dropped after TLS1.2.
|
||||
tls.DEFAULT_MAX_VERSION = 'TLSv1.2';
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
};
|
||||
|
||||
const server = tls.Server(options, common.mustCall((socket) => {
|
||||
console.log('Server: New connection received');
|
||||
socket.on('error', common.mustCall((err) => {
|
||||
console.log('Server: Error received:', err.message);
|
||||
common.expectsError({
|
||||
name: 'Error',
|
||||
code: 'ERR_TLS_RENEGOTIATION_DISABLED',
|
||||
message: 'TLS session renegotiation disabled for this socket'
|
||||
})(err);
|
||||
socket.destroy();
|
||||
server.close();
|
||||
}));
|
||||
// Disable renegotiation after the first chunk of data received.
|
||||
// Demonstrates that renegotiation works successfully up until
|
||||
// disableRenegotiation is called.
|
||||
socket.on('data', common.mustCall((chunk) => {
|
||||
console.log('Server: Data received:', chunk.toString());
|
||||
socket.write(chunk);
|
||||
console.log('Server: Disabling renegotiation');
|
||||
socket.disableRenegotiation();
|
||||
}));
|
||||
socket.on('secure', common.mustCall(() => {
|
||||
console.log('Server: Secure event, handshakes:', socket._handle.handshakes);
|
||||
assert(socket._handle.handshakes < 2,
|
||||
`Too many handshakes [${socket._handle.handshakes}]`);
|
||||
}));
|
||||
}));
|
||||
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const port = server.address().port;
|
||||
console.log('Server: Listening on port', port);
|
||||
const options = {
|
||||
rejectUnauthorized: false,
|
||||
port
|
||||
};
|
||||
const client = tls.connect(options, common.mustCall(() => {
|
||||
console.log('Client: Connected');
|
||||
|
||||
assert.throws(() => client.renegotiate(), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
});
|
||||
|
||||
assert.throws(() => client.renegotiate(common.mustNotCall()), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
});
|
||||
|
||||
assert.throws(() => client.renegotiate({}, false), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
});
|
||||
|
||||
assert.throws(() => client.renegotiate({}, null), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
});
|
||||
|
||||
|
||||
// Negotiation is still permitted for this first
|
||||
// attempt. This should succeed.
|
||||
let ok = client.renegotiate(options, common.mustSucceed(() => {
|
||||
console.log('Client: First renegotiation successful');
|
||||
// Once renegotiation completes, we write some
|
||||
// data to the socket, which triggers the on
|
||||
// data event on the server. After that data
|
||||
// is received, disableRenegotiation is called.
|
||||
client.write('data', common.mustCall(() => {
|
||||
console.log('Client: Data written');
|
||||
// This second renegotiation attempt should fail
|
||||
// and the callback should never be invoked. The
|
||||
// server will simply drop the connection after
|
||||
// emitting the error.
|
||||
ok = client.renegotiate(options, common.mustNotCall());
|
||||
console.log('Client: Second renegotiation attempt, ok:', ok);
|
||||
assert.strictEqual(ok, true);
|
||||
}));
|
||||
}));
|
||||
assert.strictEqual(ok, true);
|
||||
client.on('secureConnect', common.mustCall(() => {
|
||||
console.log('Client: secureConnect event');
|
||||
}));
|
||||
client.on('secure', common.mustCall(() => {
|
||||
console.log('Client: secure event');
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
33
test/js/node/test/parallel/test-tls-empty-sni-context.js
Normal file
33
test/js/node/test/parallel/test-tls-empty-sni-context.js
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
const options = {
|
||||
SNICallback: (name, callback) => {
|
||||
callback(null, tls.createSecureContext());
|
||||
}
|
||||
};
|
||||
|
||||
const server = tls.createServer(options, (c) => {
|
||||
assert.fail('Should not be called');
|
||||
}).on('tlsClientError', common.mustCall((err, c) => {
|
||||
assert.match(err.message, /no suitable signature algorithm/i);
|
||||
server.close();
|
||||
})).listen(0, common.mustCall(() => {
|
||||
const c = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false,
|
||||
servername: 'any.name'
|
||||
}, common.mustNotCall());
|
||||
|
||||
c.on('error', common.mustCall((err) => {
|
||||
const expectedErr = common.hasOpenSSL(3, 2) ?
|
||||
'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE' : 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE';
|
||||
assert.strictEqual(err.code, expectedErr);
|
||||
}));
|
||||
}));
|
||||
61
test/js/node/test/parallel/test-tls-enable-keylog-cli.js
Normal file
61
test/js/node/test/parallel/test-tls-enable-keylog-cli.js
Normal file
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// Test --tls-keylog CLI flag.
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const { fork } = require('child_process');
|
||||
|
||||
if (process.argv[2] === 'test')
|
||||
return test();
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
const file = tmpdir.resolve('keylog.log');
|
||||
|
||||
const child = fork(__filename, ['test'], {
|
||||
execArgv: ['--tls-keylog=' + file]
|
||||
});
|
||||
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
const log = fs.readFileSync(file, 'utf8').trim().split('\n');
|
||||
// Both client and server should log their secrets,
|
||||
// so we should have two identical lines in the log
|
||||
assert.strictEqual(log.length, 2);
|
||||
assert.strictEqual(log[0], log[1]);
|
||||
}));
|
||||
|
||||
function test() {
|
||||
const {
|
||||
connect, keys
|
||||
} = require(fixtures.path('tls-connect'));
|
||||
|
||||
connect({
|
||||
client: {
|
||||
checkServerIdentity: (servername, cert) => { },
|
||||
ca: `${keys.agent1.cert}\n${keys.agent6.ca}`,
|
||||
},
|
||||
server: {
|
||||
cert: keys.agent6.cert,
|
||||
key: keys.agent6.key,
|
||||
// Number of keylog events is dependent on protocol version
|
||||
maxVersion: 'TLSv1.2',
|
||||
},
|
||||
}, common.mustCall((err, pair, cleanup) => {
|
||||
if (pair.server.err) {
|
||||
console.trace('server', pair.server.err);
|
||||
}
|
||||
if (pair.client.err) {
|
||||
console.trace('client', pair.client.err);
|
||||
}
|
||||
assert.ifError(pair.server.err);
|
||||
assert.ifError(pair.client.err);
|
||||
|
||||
return cleanup();
|
||||
}));
|
||||
}
|
||||
46
test/js/node/test/parallel/test-tls-env-bad-extra-ca.js
Normal file
46
test/js/node/test/parallel/test-tls-env-bad-extra-ca.js
Normal file
@@ -0,0 +1,46 @@
|
||||
// Setting NODE_EXTRA_CA_CERTS to non-existent file emits a warning
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const fork = require('child_process').fork;
|
||||
const tls = require('tls');
|
||||
|
||||
if (process.env.CHILD) {
|
||||
// This will try to load the extra CA certs, and emit a warning when it fails.
|
||||
return tls.createServer({});
|
||||
}
|
||||
|
||||
const env = {
|
||||
...process.env,
|
||||
CHILD: 'yes',
|
||||
NODE_EXTRA_CA_CERTS: `${fixtures.fixturesDir}/no-such-file-exists-🐢`,
|
||||
};
|
||||
|
||||
const opts = {
|
||||
env: env,
|
||||
silent: true,
|
||||
};
|
||||
let stderr = '';
|
||||
|
||||
fork(__filename, opts)
|
||||
.on('exit', common.mustCall(function(status) {
|
||||
// Check that client succeeded in connecting.
|
||||
assert.strictEqual(status, 0);
|
||||
}))
|
||||
.on('close', common.mustCall(function() {
|
||||
// TODO(addaleax): Make `SafeGetenv` work like `process.env`
|
||||
// encoding-wise
|
||||
if (!common.isWindows) {
|
||||
const re = /Warning: Ignoring extra certs from.*no-such-file-exists-🐢.* load failed:.*No such file or directory/;
|
||||
assert.match(stderr, re);
|
||||
}
|
||||
}))
|
||||
.stderr.setEncoding('utf8').on('data', function(str) {
|
||||
stderr += str;
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('node:assert');
|
||||
const tls = require('node:tls');
|
||||
const { fork } = require('node:child_process');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const tests = [
|
||||
{
|
||||
get clientOptions() {
|
||||
const secureContext = tls.createSecureContext();
|
||||
secureContext.context.addCACert(
|
||||
fixtures.readKey('ca1-cert.pem')
|
||||
);
|
||||
|
||||
return {
|
||||
secureContext
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
clientOptions: {
|
||||
crl: fixtures.readKey('ca2-crl.pem')
|
||||
}
|
||||
},
|
||||
{
|
||||
clientOptions: {
|
||||
pfx: fixtures.readKey('agent1.pfx'),
|
||||
passphrase: 'sample'
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
if (process.argv[2]) {
|
||||
const testNumber = parseInt(process.argv[2], 10);
|
||||
assert(testNumber >= 0 && testNumber < tests.length);
|
||||
|
||||
const test = tests[testNumber];
|
||||
|
||||
const clientOptions = {
|
||||
...test.clientOptions,
|
||||
port: process.argv[3],
|
||||
checkServerIdentity: common.mustCall()
|
||||
};
|
||||
|
||||
const client = tls.connect(clientOptions, common.mustCall(() => {
|
||||
client.end('hi');
|
||||
}));
|
||||
} else {
|
||||
const serverOptions = {
|
||||
key: fixtures.readKey('agent3-key.pem'),
|
||||
cert: fixtures.readKey('agent3-cert.pem')
|
||||
};
|
||||
|
||||
for (const testNumber in tests) {
|
||||
const server = tls.createServer(serverOptions, common.mustCall((socket) => {
|
||||
socket.end('bye');
|
||||
server.close();
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const env = {
|
||||
...process.env,
|
||||
NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'ca2-cert.pem')
|
||||
};
|
||||
|
||||
const args = [
|
||||
testNumber,
|
||||
server.address().port,
|
||||
];
|
||||
|
||||
fork(__filename, args, { env }).on('exit', common.mustCall((status) => {
|
||||
assert.strictEqual(status, 0);
|
||||
}));
|
||||
}));
|
||||
}
|
||||
}
|
||||
53
test/js/node/test/parallel/test-tls-env-extra-ca.js
Normal file
53
test/js/node/test/parallel/test-tls-env-extra-ca.js
Normal file
@@ -0,0 +1,53 @@
|
||||
// Certs in NODE_EXTRA_CA_CERTS are used for TLS peer validation
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const { fork } = require('child_process');
|
||||
|
||||
if (process.env.CHILD) {
|
||||
console.log('Child process started');
|
||||
const copts = {
|
||||
port: process.env.PORT,
|
||||
checkServerIdentity: common.mustCall(),
|
||||
};
|
||||
console.log('Client options:', copts);
|
||||
const client = tls.connect(copts, common.mustCall(function() {
|
||||
console.log('Client connected successfully');
|
||||
client.end('hi');
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
};
|
||||
console.log('Server options:', options);
|
||||
|
||||
const server = tls.createServer(options, common.mustCall(function(s) {
|
||||
console.log('Server received connection');
|
||||
s.end('bye');
|
||||
server.close();
|
||||
})).listen(0, common.mustCall(function() {
|
||||
console.log('Server listening on port:', this.address().port);
|
||||
const env = {
|
||||
...process.env,
|
||||
CHILD: 'yes',
|
||||
PORT: this.address().port,
|
||||
NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'ca1-cert.pem')
|
||||
};
|
||||
|
||||
fork(__filename, { env }).on('exit', common.mustCall(function(status) {
|
||||
console.log('Child process exited with status:', status);
|
||||
// Client did not succeed in connecting
|
||||
assert.strictEqual(status, 0);
|
||||
}));
|
||||
}));
|
||||
48
test/js/node/test/parallel/test-tls-error-servername.js
Normal file
48
test/js/node/test/parallel/test-tls-error-servername.js
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
// This tests the errors thrown from TLSSocket.prototype.setServername
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const { connect, TLSSocket } = require('tls');
|
||||
const { duplexPair } = require('stream');
|
||||
const [ clientSide, serverSide ] = duplexPair();
|
||||
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
const ca = fixtures.readKey('ca1-cert.pem');
|
||||
|
||||
const client = connect({
|
||||
socket: clientSide,
|
||||
ca,
|
||||
host: 'agent1' // Hostname from certificate
|
||||
});
|
||||
|
||||
[undefined, null, 1, true, {}].forEach((value) => {
|
||||
assert.throws(() => {
|
||||
client.setServername(value);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: 'The "name" argument must be of type string.' +
|
||||
common.invalidArgTypeHelper(value)
|
||||
});
|
||||
});
|
||||
|
||||
const server = new TLSSocket(serverSide, {
|
||||
isServer: true,
|
||||
key,
|
||||
cert,
|
||||
ca
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
server.setServername('localhost');
|
||||
}, {
|
||||
code: 'ERR_TLS_SNI_FROM_SERVER',
|
||||
message: 'Cannot issue SNI from a TLS server-side socket'
|
||||
});
|
||||
122
test/js/node/test/parallel/test-tls-exportkeyingmaterial.js
Normal file
122
test/js/node/test/parallel/test-tls-exportkeyingmaterial.js
Normal file
@@ -0,0 +1,122 @@
|
||||
'use strict';
|
||||
|
||||
// Test return value of tlsSocket.exportKeyingMaterial
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
|
||||
console.log('Creating server...');
|
||||
const server = net.createServer(common.mustCall((s) => {
|
||||
console.log('Server received connection');
|
||||
const tlsSocket = new tls.TLSSocket(s, {
|
||||
isServer: true,
|
||||
server: server,
|
||||
secureContext: tls.createSecureContext({ key, cert })
|
||||
});
|
||||
|
||||
console.log('Testing exportKeyingMaterial before secure connection...');
|
||||
assert.throws(() => {
|
||||
tlsSocket.exportKeyingMaterial(128, 'label');
|
||||
}, {
|
||||
name: 'Error',
|
||||
message: 'TLS socket connection must be securely established',
|
||||
code: 'ERR_TLS_INVALID_STATE'
|
||||
});
|
||||
console.log('Assert complete.');
|
||||
|
||||
tlsSocket.on('secure', common.mustCall(() => {
|
||||
console.log('TLS connection secured');
|
||||
const label = 'client finished';
|
||||
|
||||
console.log('Testing valid keying material export...');
|
||||
const validKeyingMaterial = tlsSocket.exportKeyingMaterial(128, label);
|
||||
assert.strictEqual(validKeyingMaterial.length, 128);
|
||||
console.log('Valid keying material length:', validKeyingMaterial.length);
|
||||
|
||||
console.log('Testing keying material with context...');
|
||||
const validKeyingMaterialWithContext = tlsSocket
|
||||
.exportKeyingMaterial(128, label, Buffer.from([0, 1, 2, 3]));
|
||||
assert.strictEqual(validKeyingMaterialWithContext.length, 128);
|
||||
console.log('Keying material with context length:', validKeyingMaterialWithContext.length);
|
||||
|
||||
// Ensure providing a context results in a different key than without
|
||||
assert.notStrictEqual(validKeyingMaterial, validKeyingMaterialWithContext);
|
||||
console.log('Verified different keys for with/without context');
|
||||
|
||||
console.log('Testing keying material with empty context...');
|
||||
const validKeyingMaterialWithEmptyContext = tlsSocket
|
||||
.exportKeyingMaterial(128, label, Buffer.from([]));
|
||||
assert.strictEqual(validKeyingMaterialWithEmptyContext.length, 128);
|
||||
console.log('Empty context keying material length:', validKeyingMaterialWithEmptyContext.length);
|
||||
|
||||
console.log('Testing invalid argument types...');
|
||||
assert.throws(() => {
|
||||
tlsSocket.exportKeyingMaterial(128, label, 'stringAsContextNotSupported');
|
||||
}, {
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
tlsSocket.exportKeyingMaterial(128, label, 1234);
|
||||
}, {
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
tlsSocket.exportKeyingMaterial(10, null);
|
||||
}, {
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
tlsSocket.exportKeyingMaterial('length', 1234);
|
||||
}, {
|
||||
name: 'TypeError',
|
||||
code: 'ERR_INVALID_ARG_TYPE'
|
||||
});
|
||||
|
||||
console.log('Testing invalid range values...');
|
||||
assert.throws(() => {
|
||||
tlsSocket.exportKeyingMaterial(-3, 'a');
|
||||
}, {
|
||||
name: 'RangeError',
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
tlsSocket.exportKeyingMaterial(0, 'a');
|
||||
}, {
|
||||
name: 'RangeError',
|
||||
code: 'ERR_OUT_OF_RANGE'
|
||||
});
|
||||
|
||||
console.log('Closing TLS socket and server...');
|
||||
tlsSocket.end();
|
||||
server.close();
|
||||
}));
|
||||
})).listen(0, () => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
const opts = {
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
};
|
||||
|
||||
console.log('Connecting client...');
|
||||
tls.connect(opts, common.mustCall(function() {
|
||||
console.log('Client connected');
|
||||
this.end();
|
||||
}));
|
||||
});
|
||||
16
test/js/node/test/parallel/test-tls-external-accessor.js
Normal file
16
test/js/node/test/parallel/test-tls-external-accessor.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
// Ensure accessing ._external doesn't hit an assert in the accessor method.
|
||||
{
|
||||
const pctx = tls.createSecureContext().context;
|
||||
const cctx = { __proto__: pctx };
|
||||
assert.throws(() => cctx._external, TypeError);
|
||||
pctx._external; // eslint-disable-line no-unused-expressions
|
||||
}
|
||||
66
test/js/node/test/parallel/test-tls-finished.js
Normal file
66
test/js/node/test/parallel/test-tls-finished.js
Normal file
@@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
// This test ensures that tlsSocket.getFinished() and
|
||||
// tlsSocket.getPeerFinished() return undefined before
|
||||
// secure connection is established, and return non-empty
|
||||
// Buffer objects with Finished messages afterwards, also
|
||||
// verifying alice.getFinished() == bob.getPeerFinished()
|
||||
// and alice.getPeerFinished() == bob.getFinished().
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
const msg = {};
|
||||
const pem = (n) => fixtures.readKey(`${n}.pem`);
|
||||
const server = tls.createServer({
|
||||
key: pem('agent1-key'),
|
||||
cert: pem('agent1-cert')
|
||||
}, common.mustCall((alice) => {
|
||||
msg.server = {
|
||||
alice: alice.getFinished(),
|
||||
bob: alice.getPeerFinished()
|
||||
};
|
||||
server.close();
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const bob = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(() => {
|
||||
msg.client = {
|
||||
alice: bob.getPeerFinished(),
|
||||
bob: bob.getFinished()
|
||||
};
|
||||
bob.end();
|
||||
}));
|
||||
|
||||
msg.before = {
|
||||
alice: bob.getPeerFinished(),
|
||||
bob: bob.getFinished()
|
||||
};
|
||||
}));
|
||||
|
||||
process.on('exit', () => {
|
||||
assert.strictEqual(undefined, msg.before.alice);
|
||||
assert.strictEqual(undefined, msg.before.bob);
|
||||
|
||||
assert(Buffer.isBuffer(msg.server.alice));
|
||||
assert(Buffer.isBuffer(msg.server.bob));
|
||||
assert(Buffer.isBuffer(msg.client.alice));
|
||||
assert(Buffer.isBuffer(msg.client.bob));
|
||||
|
||||
assert(msg.server.alice.length > 0);
|
||||
assert(msg.server.bob.length > 0);
|
||||
assert(msg.client.alice.length > 0);
|
||||
assert(msg.client.bob.length > 0);
|
||||
|
||||
assert(msg.server.alice.equals(msg.client.alice));
|
||||
assert(msg.server.bob.equals(msg.client.bob));
|
||||
});
|
||||
38
test/js/node/test/parallel/test-tls-generic-stream.js
Normal file
38
test/js/node/test/parallel/test-tls-generic-stream.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { duplexPair } = require('stream');
|
||||
const assert = require('assert');
|
||||
const { TLSSocket, connect } = require('tls');
|
||||
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
const ca = fixtures.readKey('ca1-cert.pem');
|
||||
|
||||
const [ clientSide, serverSide ] = duplexPair();
|
||||
|
||||
const clientTLS = connect({
|
||||
socket: clientSide,
|
||||
ca,
|
||||
host: 'agent1' // Hostname from certificate
|
||||
});
|
||||
const serverTLS = new TLSSocket(serverSide, {
|
||||
isServer: true,
|
||||
key,
|
||||
cert,
|
||||
ca
|
||||
});
|
||||
|
||||
assert.strictEqual(clientTLS.connecting, false);
|
||||
assert.strictEqual(serverTLS.connecting, false);
|
||||
|
||||
clientTLS.on('secureConnect', common.mustCall(() => {
|
||||
clientTLS.write('foobar', common.mustCall(() => {
|
||||
assert.strictEqual(serverTLS.read().toString(), 'foobar');
|
||||
assert.strictEqual(clientTLS._handle.writeQueueSize, 0);
|
||||
}));
|
||||
assert.ok(clientTLS._handle.writeQueueSize > 0);
|
||||
}));
|
||||
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
// Flags: --no-use-openssl-ca
|
||||
// This tests that tls.getCACertificates() returns the bundled
|
||||
// certificates correctly.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
const defaultSet = new Set(tls.getCACertificates('default'));
|
||||
const bundledSet = new Set(tls.getCACertificates('bundled'));
|
||||
|
||||
// When --use-openssl-ca is false (i.e. bundled CA is sued),
|
||||
// default is a superset of bundled certificates.
|
||||
assert.deepStrictEqual(defaultSet.intersection(bundledSet), bundledSet);
|
||||
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
// This tests that tls.getCACertificates() returns the bundled
|
||||
// certificates correctly.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const { assertIsCAArray } = require('../common/tls');
|
||||
|
||||
const certs = tls.getCACertificates('bundled');
|
||||
assertIsCAArray(certs);
|
||||
|
||||
// It's the same as tls.rootCertificates - both are
|
||||
// Mozilla CA stores across platform.
|
||||
assert.strictEqual(certs, tls.rootCertificates);
|
||||
|
||||
// It's cached on subsequent accesses.
|
||||
assert.strictEqual(certs, tls.getCACertificates('bundled'));
|
||||
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
// This tests that tls.getCACertificates() returns the default
|
||||
// certificates correctly.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const { assertIsCAArray } = require('../common/tls');
|
||||
|
||||
const certs = tls.getCACertificates();
|
||||
assertIsCAArray(certs);
|
||||
|
||||
const certs2 = tls.getCACertificates('default');
|
||||
assert.strictEqual(certs, certs2);
|
||||
|
||||
// It's cached on subsequent accesses.
|
||||
assert.strictEqual(certs, tls.getCACertificates('default'));
|
||||
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
// This tests that tls.getCACertificates() throws error when being
|
||||
// passed an invalid argument.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
for (const invalid of [1, null, () => {}, true]) {
|
||||
assert.throws(() => tls.getCACertificates(invalid), {
|
||||
code: 'ERR_INVALID_ARG_TYPE'
|
||||
});
|
||||
}
|
||||
|
||||
assert.throws(() => tls.getCACertificates('test'), {
|
||||
code: 'ERR_INVALID_ARG_VALUE'
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
// This tests that tls.getCACertificates('extra') returns an empty
|
||||
// array if NODE_EXTRA_CA_CERTS is empty.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const fs = require('fs');
|
||||
|
||||
const assert = require('assert');
|
||||
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
tmpdir.refresh();
|
||||
const certsJSON = tmpdir.resolve('certs.json');
|
||||
|
||||
// If NODE_EXTRA_CA_CERTS is not set, it should be an empty array.
|
||||
spawnSyncAndExitWithoutError(process.execPath, [fixtures.path('tls-get-ca-certificates.js')], {
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_EXTRA_CA_CERTS: undefined,
|
||||
CA_TYPE: 'extra',
|
||||
CA_OUT: certsJSON,
|
||||
}
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(fs.readFileSync(certsJSON, 'utf-8'));
|
||||
assert.deepStrictEqual(parsed, []);
|
||||
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
// This tests that tls.getCACertificates('defulat') returns a superset
|
||||
// of tls.getCACertificates('extra') when NODE_EXTRA_CA_CERTS is used.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
spawnSyncAndExitWithoutError(process.execPath, [fixtures.path('tls-check-extra-ca-certificates.js')], {
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'ca1-cert.pem'),
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
// This tests that tls.getCACertificates('extra') returns the extra
|
||||
// certificates from NODE_EXTRA_CA_CERTS correctly.
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const fs = require('fs');
|
||||
const assert = require('assert');
|
||||
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
tmpdir.refresh();
|
||||
const certsJSON = tmpdir.resolve('certs.json');
|
||||
|
||||
// If NODE_EXTRA_CA_CERTS is set, it should contain a list of certificates.
|
||||
spawnSyncAndExitWithoutError(process.execPath, [fixtures.path('tls-get-ca-certificates.js')], {
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'ca1-cert.pem'),
|
||||
CA_TYPE: 'extra',
|
||||
CA_OUT: certsJSON,
|
||||
}
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(fs.readFileSync(certsJSON, 'utf-8'));
|
||||
assert.deepStrictEqual(parsed, [fixtures.readKey('ca1-cert.pem', 'utf8')]);
|
||||
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
// This tests that tls.getCACertificates() returns the system
|
||||
// certificates correctly when --use-system-ca is disabled.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const fs = require('fs');
|
||||
|
||||
const assert = require('assert');
|
||||
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
|
||||
const certs = tls.getCACertificates('system');
|
||||
if (certs.length === 0) {
|
||||
common.skip('No trusted system certificates installed. Skip.');
|
||||
}
|
||||
|
||||
tmpdir.refresh();
|
||||
const certsJSON = tmpdir.resolve('certs.json');
|
||||
spawnSyncAndExitWithoutError(process.execPath, [
|
||||
'--no-use-system-ca',
|
||||
fixtures.path('tls-get-ca-certificates.js'),
|
||||
], {
|
||||
env: {
|
||||
...process.env,
|
||||
CA_TYPE: 'system',
|
||||
CA_OUT: certsJSON,
|
||||
}
|
||||
});
|
||||
|
||||
const parsed = JSON.parse(fs.readFileSync(certsJSON, 'utf-8'));
|
||||
assert.deepStrictEqual(parsed, certs);
|
||||
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
// Flags: --use-system-ca
|
||||
// This tests that tls.getCACertificates() returns the system
|
||||
// certificates correctly.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const { assertIsCAArray } = require('../common/tls');
|
||||
|
||||
const systemCerts = tls.getCACertificates('system');
|
||||
// Usually Windows come with some certificates installed by default.
|
||||
// This can't be said about other systems, in that case check that
|
||||
// at least systemCerts is an array (which may be empty).
|
||||
if (common.isWindows) {
|
||||
assertIsCAArray(systemCerts);
|
||||
} else {
|
||||
assert(Array.isArray(systemCerts));
|
||||
}
|
||||
|
||||
// When --use-system-ca is true, default is a superset of system
|
||||
// certificates.
|
||||
const defaultCerts = tls.getCACertificates('default');
|
||||
assert(defaultCerts.length >= systemCerts.length);
|
||||
const defaultSet = new Set(defaultCerts);
|
||||
const systemSet = new Set(systemCerts);
|
||||
assert.deepStrictEqual(defaultSet.intersection(systemSet), systemSet);
|
||||
|
||||
// It's cached on subsequent accesses.
|
||||
assert.strictEqual(systemCerts, tls.getCACertificates('system'));
|
||||
53
test/js/node/test/parallel/test-tls-get-cert-chains-in-ca.js
Normal file
53
test/js/node/test/parallel/test-tls-get-cert-chains-in-ca.js
Normal file
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// Check cert chain is received by client, and is completed with the ca cert
|
||||
// known to the client.
|
||||
|
||||
const {
|
||||
assert, connect, debug, keys
|
||||
} = require(fixtures.path('tls-connect'));
|
||||
|
||||
|
||||
// agent6-cert.pem includes cert for agent6 and ca3, split it apart and
|
||||
// provide ca3 in the .ca property.
|
||||
const agent6Chain = keys.agent6.cert.split(/(?=-----BEGIN CERTIFICATE-----)/);
|
||||
const agent6End = agent6Chain[0];
|
||||
const agent6Middle = agent6Chain[1];
|
||||
console.log('Agent6 chain split:', { agent6End, agent6Middle });
|
||||
|
||||
connect({
|
||||
client: {
|
||||
checkServerIdentity: (servername, cert) => {
|
||||
console.log('checkServerIdentity', servername, cert);
|
||||
},
|
||||
ca: keys.agent6.ca,
|
||||
},
|
||||
server: {
|
||||
cert: agent6End,
|
||||
key: keys.agent6.key,
|
||||
ca: agent6Middle,
|
||||
},
|
||||
}, function(err, pair, cleanup) {
|
||||
console.log('Connection error:', err);
|
||||
assert.ifError(err);
|
||||
|
||||
const peer = pair.client.conn.getPeerCertificate();
|
||||
console.log('Peer certificate:', peer);
|
||||
debug('peer:\n', peer);
|
||||
assert.match(peer.serialNumber, /5B75D77EDC7FB5B7FA9F1424DA4C64FB815DCBDE/i);
|
||||
|
||||
const next = pair.client.conn.getPeerCertificate(true).issuerCertificate;
|
||||
console.log('Next certificate:', next);
|
||||
const root = next.issuerCertificate;
|
||||
delete next.issuerCertificate;
|
||||
debug('next:\n', next);
|
||||
assert.match(next.serialNumber, /147D36C1C2F74206DE9FAB5F2226D78ADB00A425/i);
|
||||
|
||||
console.log('Root certificate:', root);
|
||||
debug('root:\n', root);
|
||||
assert.match(root.serialNumber, /4AB16C8DFD6A7D0D2DFCABDF9C4B0E92C6AD0229/i);
|
||||
|
||||
return cleanup();
|
||||
});
|
||||
39
test/js/node/test/parallel/test-tls-getcertificate-x509.js
Normal file
39
test/js/node/test/parallel/test-tls-getcertificate-x509.js
Normal file
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { X509Certificate } = require('crypto');
|
||||
|
||||
console.log(fixtures.readKey('agent6-key.pem'));
|
||||
const options = {
|
||||
key: fixtures.readKey('agent6-key.pem'),
|
||||
cert: fixtures.readKey('agent6-cert.pem')
|
||||
};
|
||||
|
||||
const server = tls.createServer(options, function(cleartext) {
|
||||
cleartext.end('World');
|
||||
});
|
||||
|
||||
server.once('secureConnection', common.mustCall(function(socket) {
|
||||
const cert = socket.getX509Certificate();
|
||||
assert(cert instanceof X509Certificate);
|
||||
assert.match(cert.serialNumber, /5B75D77EDC7FB5B7FA9F1424DA4C64FB815DCBDE/i);
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(function() {
|
||||
const socket = tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(function() {
|
||||
const peerCert = socket.getPeerX509Certificate();
|
||||
assert(peerCert.issuerCertificate instanceof X509Certificate);
|
||||
assert.strictEqual(peerCert.issuerCertificate.issuerCertificate, undefined);
|
||||
assert.match(peerCert.issuerCertificate.serialNumber, /147D36C1C2F74206DE9FAB5F2226D78ADB00A425/i);
|
||||
server.close();
|
||||
}));
|
||||
socket.end('Hello');
|
||||
}));
|
||||
57
test/js/node/test/parallel/test-tls-handshake-exception.js
Normal file
57
test/js/node/test/parallel/test-tls-handshake-exception.js
Normal file
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
// Verify that exceptions from a callback don't result in
|
||||
// failed CHECKs when trying to print the exception message.
|
||||
|
||||
// This test is convoluted because it needs to trigger a callback
|
||||
// into JS land at just the right time when an exception is pending,
|
||||
// and does so by exploiting a weakness in the streams infrastructure.
|
||||
// I won't shed any tears if this test ever becomes invalidated.
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
if (process.argv[2] === 'child') {
|
||||
const fixtures = require('../common/fixtures');
|
||||
const https = require('https');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const { Duplex } = require('stream');
|
||||
const { mustCall } = common;
|
||||
|
||||
const cert = fixtures.readKey('rsa_cert.crt');
|
||||
const key = fixtures.readKey('rsa_private.pem');
|
||||
|
||||
net.createServer(mustCall(onplaintext)).listen(0, mustCall(onlisten));
|
||||
|
||||
function onlisten() {
|
||||
const { port } = this.address();
|
||||
https.get({ port, rejectUnauthorized: false });
|
||||
}
|
||||
|
||||
function onplaintext(c) {
|
||||
const d = new class extends Duplex {
|
||||
_read(n) {
|
||||
const data = c.read(n);
|
||||
if (data) d.push(data);
|
||||
}
|
||||
_write(...xs) {
|
||||
c.write(...xs);
|
||||
}
|
||||
}();
|
||||
c.on('data', d.push.bind(d));
|
||||
|
||||
const options = { key, cert };
|
||||
const fail = () => { throw new Error('eyecatcher'); };
|
||||
tls.createServer(options, mustCall(fail)).emit('connection', d);
|
||||
}
|
||||
} else {
|
||||
const assert = require('assert');
|
||||
const { spawnSync } = require('child_process');
|
||||
const result = spawnSync(process.execPath, [__filename, 'child']);
|
||||
const stderr = result.stderr.toString();
|
||||
const ok = stderr.includes('Error: eyecatcher');
|
||||
assert(ok, stderr);
|
||||
}
|
||||
66
test/js/node/test/parallel/test-tls-hello-parser-failure.js
Normal file
66
test/js/node/test/parallel/test-tls-hello-parser-failure.js
Normal file
@@ -0,0 +1,66 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// This test ensures that the tls parser causes a client error if the client
|
||||
// sends invalid data.
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
const net = require('net');
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('rsa_private.pem'),
|
||||
cert: fixtures.readKey('rsa_cert.crt')
|
||||
};
|
||||
|
||||
const bonkers = Buffer.alloc(1024 * 1024, 42);
|
||||
|
||||
const server = tls.createServer(options, function(c) {
|
||||
|
||||
}).listen(0, common.mustCall(function() {
|
||||
const client = net.connect(this.address().port, common.mustCall(function() {
|
||||
client.write(bonkers);
|
||||
}));
|
||||
|
||||
const writeAgain = setImmediate(function() {
|
||||
client.write(bonkers);
|
||||
});
|
||||
|
||||
client.once('error', common.mustCall(function(err) {
|
||||
clearImmediate(writeAgain);
|
||||
client.destroy();
|
||||
server.close();
|
||||
}));
|
||||
|
||||
client.on('close', common.mustCall(function(hadError) {
|
||||
// Confirm that client errored
|
||||
assert.strictEqual(hadError, true);
|
||||
}));
|
||||
}));
|
||||
23
test/js/node/test/parallel/test-tls-invalid-pfx.js
Normal file
23
test/js/node/test/parallel/test-tls-invalid-pfx.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const {
|
||||
assert, connect, keys
|
||||
} = require(fixtures.path('tls-connect'));
|
||||
|
||||
const invalidPfx = fixtures.readKey('cert-without-key.pfx');
|
||||
|
||||
connect({
|
||||
client: {
|
||||
pfx: invalidPfx,
|
||||
passphrase: 'test',
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
server: keys.agent1
|
||||
}, common.mustCall((e, pair, cleanup) => {
|
||||
assert.strictEqual(e.message, 'Unable to load private key from PFX data');
|
||||
cleanup();
|
||||
}));
|
||||
@@ -0,0 +1,41 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
|
||||
// This test expects `tls.connect()` to emit a warning when
|
||||
// `servername` of options is an IP address.
|
||||
common.expectWarning(
|
||||
'DeprecationWarning',
|
||||
'Setting the TLS ServerName to an IP address is not permitted by ' +
|
||||
'RFC 6066. This will be ignored in a future version.',
|
||||
'DEP0123'
|
||||
);
|
||||
|
||||
{
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem')
|
||||
};
|
||||
|
||||
const server = tls.createServer(options, function(s) {
|
||||
s.end('hello');
|
||||
}).listen(0, function() {
|
||||
const client = tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
servername: '127.0.0.1',
|
||||
}, function() {
|
||||
client.end();
|
||||
});
|
||||
});
|
||||
|
||||
server.on('connection', common.mustCall(function(socket) {
|
||||
server.close();
|
||||
}));
|
||||
}
|
||||
66
test/js/node/test/parallel/test-tls-js-stream.js
Normal file
66
test/js/node/test/parallel/test-tls-js-stream.js
Normal file
@@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const net = require('net');
|
||||
const stream = require('stream');
|
||||
const tls = require('tls');
|
||||
|
||||
const server = tls.createServer({
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem')
|
||||
}, common.mustCall(function(c) {
|
||||
console.log('new client');
|
||||
|
||||
c.resume();
|
||||
c.end('ohai');
|
||||
})).listen(0, common.mustCall(function() {
|
||||
const raw = net.connect(this.address().port);
|
||||
|
||||
let pending = false;
|
||||
raw.on('readable', function() {
|
||||
if (pending)
|
||||
p._read();
|
||||
});
|
||||
|
||||
raw.on('end', function() {
|
||||
p.push(null);
|
||||
});
|
||||
|
||||
const p = new stream.Duplex({
|
||||
read: function read() {
|
||||
pending = false;
|
||||
|
||||
const chunk = raw.read();
|
||||
if (chunk) {
|
||||
console.log('read', chunk);
|
||||
this.push(chunk);
|
||||
} else {
|
||||
pending = true;
|
||||
}
|
||||
},
|
||||
write: function write(data, enc, cb) {
|
||||
console.log('write', data, enc);
|
||||
raw.write(data, enc, cb);
|
||||
}
|
||||
});
|
||||
|
||||
const socket = tls.connect({
|
||||
socket: p,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(function() {
|
||||
console.log('client secure');
|
||||
|
||||
socket.resume();
|
||||
socket.end('hello');
|
||||
}));
|
||||
|
||||
socket.once('close', function() {
|
||||
console.log('client close');
|
||||
server.close();
|
||||
});
|
||||
}));
|
||||
41
test/js/node/test/parallel/test-tls-junk-server.js
Normal file
41
test/js/node/test/parallel/test-tls-junk-server.js
Normal file
@@ -0,0 +1,41 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const https = require('https');
|
||||
const net = require('net');
|
||||
|
||||
console.log('Starting TLS junk server test');
|
||||
|
||||
const server = net.createServer(function(s) {
|
||||
console.log('Server received connection');
|
||||
s.once('data', function() {
|
||||
console.log('Server received data');
|
||||
s.end('I was waiting for you, hello!', function() {
|
||||
console.log('Server sent response');
|
||||
s.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(0, function() {
|
||||
console.log('Server listening on port:', this.address().port);
|
||||
const req = https.request({ port: this.address().port });
|
||||
req.end();
|
||||
console.log('HTTPS request sent');
|
||||
|
||||
let expectedErrorMessage = new RegExp('wrong version number');
|
||||
if (common.hasOpenSSL(3, 2)) {
|
||||
console.log('Using OpenSSL 3.2+ error message pattern');
|
||||
expectedErrorMessage = new RegExp('packet length too long');
|
||||
}
|
||||
req.once('error', common.mustCall(function(err) {
|
||||
console.log('Received error:', err.message);
|
||||
assert(expectedErrorMessage.test(err.message));
|
||||
server.close();
|
||||
console.log('Test completed');
|
||||
}));
|
||||
});
|
||||
36
test/js/node/test/parallel/test-tls-keylog-tlsv13.js
Normal file
36
test/js/node/test/parallel/test-tls-keylog-tlsv13.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const server = tls.createServer({
|
||||
key: fixtures.readKey('agent2-key.pem'),
|
||||
cert: fixtures.readKey('agent2-cert.pem'),
|
||||
// Amount of keylog events depends on negotiated protocol
|
||||
// version, so force a specific one:
|
||||
minVersion: 'TLSv1.3',
|
||||
maxVersion: 'TLSv1.3',
|
||||
}).listen(() => {
|
||||
const client = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
|
||||
server.on('keylog', common.mustCall((line, tlsSocket) => {
|
||||
assert(Buffer.isBuffer(line));
|
||||
assert.strictEqual(tlsSocket.encrypted, true);
|
||||
}, 5));
|
||||
client.on('keylog', common.mustCall((line) => {
|
||||
assert(Buffer.isBuffer(line));
|
||||
}, 5));
|
||||
|
||||
client.once('secureConnect', () => {
|
||||
server.close();
|
||||
client.end();
|
||||
});
|
||||
});
|
||||
15
test/js/node/test/parallel/test-tls-legacy-deprecated.js
Normal file
15
test/js/node/test/parallel/test-tls-legacy-deprecated.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// Flags: --no-warnings
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
|
||||
common.expectWarning(
|
||||
'DeprecationWarning',
|
||||
'tls.createSecurePair() is deprecated. Please use tls.TLSSocket instead.',
|
||||
'DEP0064'
|
||||
);
|
||||
|
||||
tls.createSecurePair();
|
||||
33
test/js/node/test/parallel/test-tls-lookup.js
Normal file
33
test/js/node/test/parallel/test-tls-lookup.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
['foobar', 1, {}, []].forEach(function connectThrows(input) {
|
||||
const opts = {
|
||||
host: 'localhost',
|
||||
port: common.PORT,
|
||||
lookup: input,
|
||||
};
|
||||
|
||||
assert.throws(() => {
|
||||
tls.connect(opts);
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
});
|
||||
});
|
||||
|
||||
connectDoesNotThrow(common.mustCall());
|
||||
|
||||
function connectDoesNotThrow(input) {
|
||||
const opts = {
|
||||
host: 'localhost',
|
||||
port: common.PORT,
|
||||
lookup: input,
|
||||
};
|
||||
|
||||
tls.connect(opts);
|
||||
}
|
||||
54
test/js/node/test/parallel/test-tls-multi-pfx.js
Normal file
54
test/js/node/test/parallel/test-tls-multi-pfx.js
Normal file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const options = {
|
||||
pfx: [
|
||||
{
|
||||
buf: fixtures.readKey('agent1.pfx'),
|
||||
passphrase: 'sample'
|
||||
},
|
||||
fixtures.readKey('ec.pfx'),
|
||||
]
|
||||
};
|
||||
|
||||
const ciphers = [];
|
||||
|
||||
const server = tls.createServer(options, function(conn) {
|
||||
conn.end('ok');
|
||||
}).listen(0, function() {
|
||||
const ecdsa = tls.connect(this.address().port, {
|
||||
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
|
||||
maxVersion: 'TLSv1.2',
|
||||
rejectUnauthorized: false,
|
||||
}, common.mustCall(function() {
|
||||
ciphers.push(ecdsa.getCipher());
|
||||
const rsa = tls.connect(server.address().port, {
|
||||
ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
|
||||
maxVersion: 'TLSv1.2',
|
||||
rejectUnauthorized: false,
|
||||
}, common.mustCall(function() {
|
||||
ciphers.push(rsa.getCipher());
|
||||
ecdsa.end();
|
||||
rsa.end();
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.deepStrictEqual(ciphers, [{
|
||||
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
|
||||
standardName: 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384',
|
||||
version: 'TLSv1.2'
|
||||
}, {
|
||||
name: 'ECDHE-RSA-AES256-GCM-SHA384',
|
||||
standardName: 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',
|
||||
version: 'TLSv1.2'
|
||||
}]);
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
// test-tls-net-socket-keepalive specifically for TLS1.2.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
|
||||
tls.DEFAULT_MAX_VERSION = 'TLSv1.2';
|
||||
|
||||
require('./test-tls-net-socket-keepalive.js');
|
||||
57
test/js/node/test/parallel/test-tls-net-socket-keepalive.js
Normal file
57
test/js/node/test/parallel/test-tls-net-socket-keepalive.js
Normal file
@@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
|
||||
// This test ensures that when tls sockets are created with `allowHalfOpen`,
|
||||
// they won't hang.
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
const ca = fixtures.readKey('ca1-cert.pem');
|
||||
const options = {
|
||||
key,
|
||||
cert,
|
||||
ca: [ca],
|
||||
};
|
||||
|
||||
const server = tls.createServer(options, common.mustCall((conn) => {
|
||||
conn.write('hello', common.mustCall());
|
||||
conn.on('data', common.mustCall());
|
||||
conn.on('end', common.mustCall());
|
||||
conn.on('data', common.mustCall());
|
||||
conn.on('close', common.mustCall());
|
||||
conn.end();
|
||||
})).listen(0, common.mustCall(() => {
|
||||
const netSocket = new net.Socket({
|
||||
allowHalfOpen: true,
|
||||
});
|
||||
|
||||
const socket = tls.connect({
|
||||
socket: netSocket,
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
|
||||
const { port, address } = server.address();
|
||||
|
||||
// Doing `net.Socket.connect()` after `tls.connect()` will make tls module
|
||||
// wrap the socket in StreamWrap.
|
||||
netSocket.connect({
|
||||
port,
|
||||
address,
|
||||
});
|
||||
|
||||
socket.on('secureConnect', common.mustCall());
|
||||
socket.on('end', common.mustCall());
|
||||
socket.on('data', common.mustCall());
|
||||
socket.on('close', common.mustCall(() => {
|
||||
server.close();
|
||||
}));
|
||||
|
||||
socket.write('hello');
|
||||
socket.end();
|
||||
}));
|
||||
66
test/js/node/test/parallel/test-tls-no-sslv23.js
Normal file
66
test/js/node/test/parallel/test-tls-no-sslv23.js
Normal file
@@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
console.log('Testing invalid protocol method');
|
||||
assert.throws(function() {
|
||||
tls.createSecureContext({ secureProtocol: 'blargh' });
|
||||
}, {
|
||||
code: 'ERR_TLS_INVALID_PROTOCOL_METHOD',
|
||||
message: 'Unknown method: blargh',
|
||||
});
|
||||
|
||||
const errMessageSSLv2 = /SSLv2 methods disabled/;
|
||||
|
||||
console.log('Testing SSLv2 method');
|
||||
assert.throws(function() {
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv2_method' });
|
||||
}, errMessageSSLv2);
|
||||
|
||||
console.log('Testing SSLv2 client method');
|
||||
assert.throws(function() {
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv2_client_method' });
|
||||
}, errMessageSSLv2);
|
||||
|
||||
console.log('Testing SSLv2 server method');
|
||||
assert.throws(function() {
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv2_server_method' });
|
||||
}, errMessageSSLv2);
|
||||
|
||||
const errMessageSSLv3 = /SSLv3 methods disabled/;
|
||||
|
||||
console.log('Testing SSLv3 method');
|
||||
assert.throws(function() {
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv3_method' });
|
||||
}, errMessageSSLv3);
|
||||
|
||||
console.log('Testing SSLv3 client method');
|
||||
assert.throws(function() {
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv3_client_method' });
|
||||
}, errMessageSSLv3);
|
||||
|
||||
console.log('Testing SSLv3 server method');
|
||||
assert.throws(function() {
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv3_server_method' });
|
||||
}, errMessageSSLv3);
|
||||
|
||||
// Note that SSLv2 and SSLv3 are disallowed but SSLv2_method and friends are
|
||||
// still accepted. They are OpenSSL's way of saying that all known protocols
|
||||
// are supported unless explicitly disabled (which we do for SSLv2 and SSLv3.)
|
||||
console.log('Testing allowed protocol methods');
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv23_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv23_client_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'SSLv23_server_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_client_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_server_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_1_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_1_client_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_1_server_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_2_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_2_client_method' });
|
||||
tls.createSecureContext({ secureProtocol: 'TLSv1_2_server_method' });
|
||||
206
test/js/node/test/parallel/test-tls-onread-static-buffer.js
Normal file
206
test/js/node/test/parallel/test-tls-onread-static-buffer.js
Normal file
@@ -0,0 +1,206 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent2-key.pem'),
|
||||
cert: fixtures.readKey('agent2-cert.pem')
|
||||
};
|
||||
|
||||
const smallMessage = Buffer.from('hello world');
|
||||
// Used to test .pause(), so needs to be larger than the internal buffer
|
||||
const largeMessage = Buffer.alloc(64 * 1024).fill('hello world');
|
||||
|
||||
// Test typical usage
|
||||
tls.createServer(options, common.mustCall(function(socket) {
|
||||
this.close();
|
||||
socket.end(smallMessage);
|
||||
})).listen(0, function() {
|
||||
let received = 0;
|
||||
const buffers = [];
|
||||
const sockBuf = Buffer.alloc(8);
|
||||
tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
onread: {
|
||||
buffer: sockBuf,
|
||||
callback: function(nread, buf) {
|
||||
assert.strictEqual(buf, sockBuf);
|
||||
received += nread;
|
||||
buffers.push(Buffer.from(buf.slice(0, nread)));
|
||||
}
|
||||
}
|
||||
}).on('data', common.mustNotCall()).on('end', common.mustCall(() => {
|
||||
assert.strictEqual(received, smallMessage.length);
|
||||
assert.deepStrictEqual(Buffer.concat(buffers), smallMessage);
|
||||
}));
|
||||
});
|
||||
|
||||
// Test Uint8Array support
|
||||
tls.createServer(options, common.mustCall(function(socket) {
|
||||
this.close();
|
||||
socket.end(smallMessage);
|
||||
})).listen(0, function() {
|
||||
let received = 0;
|
||||
let incoming = new Uint8Array(0);
|
||||
const sockBuf = new Uint8Array(8);
|
||||
tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
onread: {
|
||||
buffer: sockBuf,
|
||||
callback: function(nread, buf) {
|
||||
assert.strictEqual(buf, sockBuf);
|
||||
received += nread;
|
||||
const newIncoming = new Uint8Array(incoming.length + nread);
|
||||
newIncoming.set(incoming);
|
||||
newIncoming.set(buf.slice(0, nread), incoming.length);
|
||||
incoming = newIncoming;
|
||||
}
|
||||
}
|
||||
}).on('data', common.mustNotCall()).on('end', common.mustCall(() => {
|
||||
assert.strictEqual(received, smallMessage.length);
|
||||
assert.deepStrictEqual(incoming, new Uint8Array(smallMessage));
|
||||
}));
|
||||
});
|
||||
|
||||
// Test Buffer callback usage
|
||||
tls.createServer(options, common.mustCall(function(socket) {
|
||||
this.close();
|
||||
socket.end(smallMessage);
|
||||
})).listen(0, function() {
|
||||
let received = 0;
|
||||
const incoming = [];
|
||||
const bufPool = [ Buffer.alloc(2), Buffer.alloc(2), Buffer.alloc(2) ];
|
||||
let bufPoolIdx = -1;
|
||||
let bufPoolUsage = 0;
|
||||
tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
onread: {
|
||||
buffer: () => {
|
||||
++bufPoolUsage;
|
||||
bufPoolIdx = (bufPoolIdx + 1) % bufPool.length;
|
||||
return bufPool[bufPoolIdx];
|
||||
},
|
||||
callback: function(nread, buf) {
|
||||
assert.strictEqual(buf, bufPool[bufPoolIdx]);
|
||||
received += nread;
|
||||
incoming.push(Buffer.from(buf.slice(0, nread)));
|
||||
}
|
||||
}
|
||||
}).on('data', common.mustNotCall()).on('end', common.mustCall(() => {
|
||||
assert.strictEqual(received, smallMessage.length);
|
||||
assert.deepStrictEqual(Buffer.concat(incoming), smallMessage);
|
||||
assert.strictEqual(bufPoolUsage, 7);
|
||||
}));
|
||||
});
|
||||
|
||||
// Test Uint8Array callback support
|
||||
tls.createServer(options, common.mustCall(function(socket) {
|
||||
this.close();
|
||||
socket.end(smallMessage);
|
||||
})).listen(0, function() {
|
||||
let received = 0;
|
||||
let incoming = new Uint8Array(0);
|
||||
const bufPool = [ new Uint8Array(2), new Uint8Array(2), new Uint8Array(2) ];
|
||||
let bufPoolIdx = -1;
|
||||
let bufPoolUsage = 0;
|
||||
tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
onread: {
|
||||
buffer: () => {
|
||||
++bufPoolUsage;
|
||||
bufPoolIdx = (bufPoolIdx + 1) % bufPool.length;
|
||||
return bufPool[bufPoolIdx];
|
||||
},
|
||||
callback: function(nread, buf) {
|
||||
assert.strictEqual(buf, bufPool[bufPoolIdx]);
|
||||
received += nread;
|
||||
const newIncoming = new Uint8Array(incoming.length + nread);
|
||||
newIncoming.set(incoming);
|
||||
newIncoming.set(buf.slice(0, nread), incoming.length);
|
||||
incoming = newIncoming;
|
||||
}
|
||||
}
|
||||
}).on('data', common.mustNotCall()).on('end', common.mustCall(() => {
|
||||
assert.strictEqual(received, smallMessage.length);
|
||||
assert.deepStrictEqual(incoming, new Uint8Array(smallMessage));
|
||||
assert.strictEqual(bufPoolUsage, 7);
|
||||
}));
|
||||
});
|
||||
|
||||
// Test explicit socket pause
|
||||
tls.createServer(options, common.mustCall(function(socket) {
|
||||
this.close();
|
||||
// Need larger message here to observe the pause
|
||||
socket.end(largeMessage);
|
||||
})).listen(0, function() {
|
||||
let received = 0;
|
||||
const buffers = [];
|
||||
const sockBuf = Buffer.alloc(64);
|
||||
let pauseScheduled = false;
|
||||
const client = tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
onread: {
|
||||
buffer: sockBuf,
|
||||
callback: function(nread, buf) {
|
||||
assert.strictEqual(buf, sockBuf);
|
||||
received += nread;
|
||||
buffers.push(Buffer.from(buf.slice(0, nread)));
|
||||
if (!pauseScheduled) {
|
||||
pauseScheduled = true;
|
||||
client.pause();
|
||||
setTimeout(() => {
|
||||
client.resume();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).on('data', common.mustNotCall()).on('end', common.mustCall(() => {
|
||||
assert.strictEqual(received, largeMessage.length);
|
||||
assert.deepStrictEqual(Buffer.concat(buffers), largeMessage);
|
||||
}));
|
||||
});
|
||||
|
||||
// Test implicit socket pause
|
||||
tls.createServer(options, common.mustCall(function(socket) {
|
||||
this.close();
|
||||
// Need larger message here to observe the pause
|
||||
socket.end(largeMessage);
|
||||
})).listen(0, function() {
|
||||
let received = 0;
|
||||
const buffers = [];
|
||||
const sockBuf = Buffer.alloc(64);
|
||||
let pauseScheduled = false;
|
||||
const client = tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
onread: {
|
||||
buffer: sockBuf,
|
||||
callback: function(nread, buf) {
|
||||
assert.strictEqual(buf, sockBuf);
|
||||
received += nread;
|
||||
buffers.push(Buffer.from(buf.slice(0, nread)));
|
||||
if (!pauseScheduled) {
|
||||
pauseScheduled = true;
|
||||
setTimeout(() => {
|
||||
client.resume();
|
||||
}, 100);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}).on('data', common.mustNotCall()).on('end', common.mustCall(() => {
|
||||
assert.strictEqual(received, largeMessage.length);
|
||||
assert.deepStrictEqual(Buffer.concat(buffers), largeMessage);
|
||||
}));
|
||||
});
|
||||
176
test/js/node/test/parallel/test-tls-over-http-tunnel.js
Normal file
176
test/js/node/test/parallel/test-tls-over-http-tunnel.js
Normal file
@@ -0,0 +1,176 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
// This test ensures that the data received through tls over http tunnel
|
||||
// is same as what is sent.
|
||||
|
||||
const assert = require('assert');
|
||||
const https = require('https');
|
||||
const net = require('net');
|
||||
const http = require('http');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
let gotRequest = false;
|
||||
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
|
||||
const options = { key, cert };
|
||||
|
||||
const server = https.createServer(options, common.mustCall((req, res) => {
|
||||
console.log('SERVER: got request');
|
||||
res.writeHead(200, {
|
||||
'content-type': 'text/plain'
|
||||
});
|
||||
console.log('SERVER: sending response');
|
||||
res.end('hello world\n');
|
||||
}));
|
||||
|
||||
const proxy = net.createServer((clientSocket) => {
|
||||
console.log('PROXY: got a client connection');
|
||||
|
||||
let serverSocket = null;
|
||||
|
||||
clientSocket.on('data', (chunk) => {
|
||||
if (!serverSocket) {
|
||||
// Verify the CONNECT request
|
||||
assert.strictEqual(chunk.toString(),
|
||||
`CONNECT localhost:${server.address().port} ` +
|
||||
'HTTP/1.1\r\n' +
|
||||
'Proxy-Connections: keep-alive\r\n' +
|
||||
`Host: localhost:${proxy.address().port}\r\n` +
|
||||
'Connection: keep-alive\r\n\r\n');
|
||||
|
||||
console.log('PROXY: got CONNECT request');
|
||||
console.log('PROXY: creating a tunnel');
|
||||
|
||||
// create the tunnel
|
||||
serverSocket = net.connect(server.address().port, common.mustCall(() => {
|
||||
console.log('PROXY: replying to client CONNECT request');
|
||||
|
||||
// Send the response
|
||||
clientSocket.write('HTTP/1.1 200 OK\r\nProxy-Connections: keep' +
|
||||
'-alive\r\nConnections: keep-alive\r\nVia: ' +
|
||||
`localhost:${proxy.address().port}\r\n\r\n`);
|
||||
}));
|
||||
|
||||
serverSocket.on('data', (chunk) => {
|
||||
clientSocket.write(chunk);
|
||||
});
|
||||
|
||||
serverSocket.on('end', common.mustCall(() => {
|
||||
clientSocket.destroy();
|
||||
}));
|
||||
} else {
|
||||
serverSocket.write(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
clientSocket.on('end', () => {
|
||||
serverSocket.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(0);
|
||||
|
||||
proxy.listen(0, common.mustCall(() => {
|
||||
console.log('CLIENT: Making CONNECT request');
|
||||
|
||||
const req = http.request({
|
||||
port: proxy.address().port,
|
||||
method: 'CONNECT',
|
||||
path: `localhost:${server.address().port}`,
|
||||
headers: {
|
||||
'Proxy-Connections': 'keep-alive'
|
||||
}
|
||||
});
|
||||
req.useChunkedEncodingByDefault = false; // for v0.6
|
||||
req.on('response', onResponse); // for v0.6
|
||||
req.on('upgrade', onUpgrade); // for v0.6
|
||||
req.on('connect', onConnect); // for v0.7 or later
|
||||
req.end();
|
||||
|
||||
function onResponse(res) {
|
||||
// Very hacky. This is necessary to avoid http-parser leaks.
|
||||
res.upgrade = true;
|
||||
}
|
||||
|
||||
function onUpgrade(res, socket, head) {
|
||||
// Hacky.
|
||||
process.nextTick(() => {
|
||||
onConnect(res, socket, head);
|
||||
});
|
||||
}
|
||||
|
||||
function onConnect(res, socket, header) {
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
console.log('CLIENT: got CONNECT response');
|
||||
|
||||
// detach the socket
|
||||
socket.removeAllListeners('data');
|
||||
socket.removeAllListeners('close');
|
||||
socket.removeAllListeners('error');
|
||||
socket.removeAllListeners('drain');
|
||||
socket.removeAllListeners('end');
|
||||
socket.ondata = null;
|
||||
socket.onend = null;
|
||||
socket.ondrain = null;
|
||||
|
||||
console.log('CLIENT: Making HTTPS request');
|
||||
|
||||
https.get({
|
||||
path: '/foo',
|
||||
key: key,
|
||||
cert: cert,
|
||||
socket: socket, // reuse the socket
|
||||
agent: false,
|
||||
rejectUnauthorized: false
|
||||
}, (res) => {
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
|
||||
res.on('data', common.mustCall((chunk) => {
|
||||
assert.strictEqual(chunk.toString(), 'hello world\n');
|
||||
console.log('CLIENT: got HTTPS response');
|
||||
gotRequest = true;
|
||||
}));
|
||||
|
||||
res.on('end', common.mustCall(() => {
|
||||
proxy.close();
|
||||
server.close();
|
||||
}));
|
||||
}).on('error', (er) => {
|
||||
// We're ok with getting ECONNRESET in this test, but it's
|
||||
// timing-dependent, and thus unreliable. Any other errors
|
||||
// are just failures, though.
|
||||
if (er.code !== 'ECONNRESET')
|
||||
throw er;
|
||||
}).end();
|
||||
}
|
||||
}));
|
||||
|
||||
process.on('exit', () => {
|
||||
assert.ok(gotRequest);
|
||||
});
|
||||
92
test/js/node/test/parallel/test-tls-pause.js
Normal file
92
test/js/node/test/parallel/test-tls-pause.js
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
// This test ensures that the data received over tls-server after pause
|
||||
// is same as what it was sent
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('rsa_private.pem'),
|
||||
cert: fixtures.readKey('rsa_cert.crt')
|
||||
};
|
||||
|
||||
const bufSize = 1024 * 1024;
|
||||
let sent = 0;
|
||||
let received = 0;
|
||||
|
||||
const server = tls.Server(options, common.mustCall((socket) => {
|
||||
socket.pipe(socket);
|
||||
socket.on('data', (c) => {
|
||||
console.error('data', c.length);
|
||||
});
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
let resumed = false;
|
||||
const client = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(() => {
|
||||
console.error('connected');
|
||||
client.pause();
|
||||
console.error('paused');
|
||||
const send = (() => {
|
||||
console.error('sending');
|
||||
const ret = client.write(Buffer.allocUnsafe(bufSize));
|
||||
console.error(`write => ${ret}`);
|
||||
if (ret !== false) {
|
||||
console.error('write again');
|
||||
sent += bufSize;
|
||||
assert.ok(sent < 100 * 1024 * 1024); // max 100MB
|
||||
return process.nextTick(send);
|
||||
}
|
||||
sent += bufSize;
|
||||
console.error(`sent: ${sent}`);
|
||||
resumed = true;
|
||||
client.resume();
|
||||
console.error('resumed', client);
|
||||
})();
|
||||
}));
|
||||
client.on('data', (data) => {
|
||||
console.error('data');
|
||||
assert.ok(resumed);
|
||||
received += data.length;
|
||||
console.error('received', received);
|
||||
console.error('sent', sent);
|
||||
if (received >= sent) {
|
||||
console.error(`received: ${received}`);
|
||||
client.end();
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
process.on('exit', () => {
|
||||
assert.strictEqual(sent, received);
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('node compiled without crypto.');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// This test ensures that TLS does not fail to read a self-signed certificate
|
||||
// and thus throw an `authorizationError`.
|
||||
// https://github.com/nodejs/node/issues/5100
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
const pfx = fixtures.readKey('agent1.pfx');
|
||||
|
||||
const server = tls
|
||||
.createServer(
|
||||
{
|
||||
pfx: pfx,
|
||||
passphrase: 'sample',
|
||||
requestCert: true,
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
common.mustCall(function(c) {
|
||||
assert.strictEqual(c.getPeerCertificate().serialNumber,
|
||||
'147D36C1C2F74206DE9FAB5F2226D78ADB00A426');
|
||||
assert.strictEqual(c.authorizationError, null);
|
||||
c.end();
|
||||
})
|
||||
)
|
||||
.listen(0, function() {
|
||||
const client = tls.connect(
|
||||
{
|
||||
port: this.address().port,
|
||||
pfx: pfx,
|
||||
passphrase: 'sample',
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
function() {
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
// Calling this repeatedly is a regression test that verifies
|
||||
// that .getCertificate() does not accidentally decrease the
|
||||
// reference count of the X509* certificate on the native side.
|
||||
assert.strictEqual(client.getCertificate().serialNumber,
|
||||
'147D36C1C2F74206DE9FAB5F2226D78ADB00A426');
|
||||
}
|
||||
client.end();
|
||||
server.close();
|
||||
}
|
||||
);
|
||||
});
|
||||
32
test/js/node/test/parallel/test-tls-psk-errors.js
Normal file
32
test/js/node/test/parallel/test-tls-psk-errors.js
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
{
|
||||
// Check tlsClientError on invalid pskIdentityHint.
|
||||
|
||||
const server = tls.createServer({
|
||||
ciphers: 'PSK+HIGH',
|
||||
pskCallback: () => {},
|
||||
pskIdentityHint: 'a'.repeat(512), // Too long identity hint.
|
||||
});
|
||||
server.on('tlsClientError', (err) => {
|
||||
assert.ok(err instanceof Error);
|
||||
assert.strictEqual(err.code, 'ERR_TLS_PSK_SET_IDENTITY_HINT_FAILED');
|
||||
server.close();
|
||||
});
|
||||
server.listen(0, () => {
|
||||
const client = tls.connect({
|
||||
port: server.address().port,
|
||||
ciphers: 'PSK+HIGH',
|
||||
checkServerIdentity: () => {},
|
||||
pskCallback: () => {},
|
||||
}, () => {});
|
||||
client.on('error', common.expectsError({ code: 'ECONNRESET' }));
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
{
|
||||
const options = {
|
||||
key: fixtures.readKey('agent11-key.pem'),
|
||||
cert: fixtures.readKey('agent11-cert.pem'),
|
||||
ciphers: 'DEFAULT'
|
||||
};
|
||||
|
||||
// Should throw error as key is too small because openssl v3 doesn't allow it
|
||||
assert.throws(() => tls.createServer(options, common.mustNotCall()),
|
||||
/key too small/i);
|
||||
|
||||
// Reducing SECLEVEL to 0 in ciphers retains compatibility with previous versions of OpenSSL like using a small key.
|
||||
// As ciphers are getting set before the cert and key get loaded.
|
||||
options.ciphers = 'DEFAULT:@SECLEVEL=0';
|
||||
assert.ok(tls.createServer(options, common.mustNotCall()));
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const util = require('util');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const sent = 'hello world';
|
||||
const serverOptions = {
|
||||
isServer: true,
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem')
|
||||
};
|
||||
|
||||
let ssl = null;
|
||||
|
||||
process.on('exit', function() {
|
||||
console.log('Exit handler called');
|
||||
assert.ok(ssl !== null);
|
||||
// If the internal pointer to stream_ isn't cleared properly then this
|
||||
// will abort.
|
||||
console.log('About to inspect ssl');
|
||||
util.inspect(ssl);
|
||||
});
|
||||
|
||||
const server = tls.createServer(serverOptions, function(s) {
|
||||
console.log('Server connection received');
|
||||
s.on('data', function() {
|
||||
console.log('Server received data');
|
||||
});
|
||||
s.on('end', function() {
|
||||
console.log('Server connection ended');
|
||||
server.close();
|
||||
s.destroy();
|
||||
});
|
||||
}).listen(0, function() {
|
||||
console.log('Server listening on port:', this.address().port);
|
||||
const c = new tls.TLSSocket();
|
||||
ssl = c.ssl;
|
||||
console.log('Created TLSSocket with ssl');
|
||||
c.connect(this.address().port, function() {
|
||||
console.log('Client connected');
|
||||
c.end(sent);
|
||||
});
|
||||
});
|
||||
52
test/js/node/test/parallel/test-tls-secure-session.js
Normal file
52
test/js/node/test/parallel/test-tls-secure-session.js
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
|
||||
// NOTE: Certificate Common Name is 'agent1'
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
|
||||
// NOTE: TLS 1.3 creates new session ticket **after** handshake so
|
||||
// `getSession()` output will be different even if the session was reused
|
||||
// during the handshake.
|
||||
secureProtocol: 'TLSv1_2_method'
|
||||
};
|
||||
|
||||
console.log('Creating TLS server with options:', options);
|
||||
|
||||
const server = tls.createServer(options, common.mustCall((socket) => {
|
||||
console.log('Server received connection');
|
||||
socket.end();
|
||||
})).listen(0, common.mustCall(() => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
let connected = false;
|
||||
let session = null;
|
||||
|
||||
const client = tls.connect({
|
||||
rejectUnauthorized: false,
|
||||
port: server.address().port,
|
||||
}, common.mustCall(() => {
|
||||
console.log('Client connected');
|
||||
assert(!connected);
|
||||
assert(!session);
|
||||
|
||||
connected = true;
|
||||
}));
|
||||
|
||||
client.on('session', common.mustCall((newSession) => {
|
||||
console.log('Client received session');
|
||||
assert(connected);
|
||||
assert(!session);
|
||||
|
||||
session = newSession;
|
||||
|
||||
client.end();
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
25
test/js/node/test/parallel/test-tls-securepair-fiftharg.js
Normal file
25
test/js/node/test/parallel/test-tls-securepair-fiftharg.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const sslcontext = tls.createSecureContext({
|
||||
cert: fixtures.readKey('rsa_cert.crt'),
|
||||
key: fixtures.readKey('rsa_private.pem')
|
||||
});
|
||||
|
||||
const pair = tls.createSecurePair(sslcontext, true, false, false, {
|
||||
SNICallback: common.mustCall((servername, cb) => {
|
||||
assert.strictEqual(servername, 'www.google.com');
|
||||
})
|
||||
});
|
||||
|
||||
// Captured traffic from browser's request to https://www.google.com
|
||||
const sslHello = fixtures.readSync('google_ssl_hello.bin');
|
||||
|
||||
pair.encrypted.write(sslHello);
|
||||
28
test/js/node/test/parallel/test-tls-securepair-leak.js
Normal file
28
test/js/node/test/parallel/test-tls-securepair-leak.js
Normal file
@@ -0,0 +1,28 @@
|
||||
// Flags: --expose-gc --no-deprecation
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const { createSecureContext } = require('tls');
|
||||
const { createSecurePair } = require('tls');
|
||||
|
||||
const before = process.memoryUsage().external;
|
||||
{
|
||||
const context = createSecureContext();
|
||||
const options = {};
|
||||
for (let i = 0; i < 1e4; i += 1)
|
||||
createSecurePair(context, false, false, false, options).destroy();
|
||||
}
|
||||
setImmediate(() => {
|
||||
global.gc();
|
||||
const after = process.memoryUsage().external;
|
||||
|
||||
// It's not an exact science but a SecurePair grows .external by about 45 KiB.
|
||||
// Unless AdjustAmountOfExternalAllocatedMemory() is called on destruction,
|
||||
// 10,000 instances make it grow by well over 400 MiB. Allow for some slop
|
||||
// because objects like buffers also affect the external limit.
|
||||
assert(after - before < 25 << 20);
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const events = require('events');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { createServer, connect } = require('tls');
|
||||
const cert = fixtures.readKey('rsa_cert.crt');
|
||||
const key = fixtures.readKey('rsa_private.pem');
|
||||
|
||||
console.log('Setting up event capture rejections...');
|
||||
events.captureRejections = true;
|
||||
|
||||
console.log('Creating TLS server...');
|
||||
const server = createServer({ cert, key }, common.mustCall(async (sock) => {
|
||||
console.log('Server received connection');
|
||||
server.close();
|
||||
console.log('Server closed');
|
||||
|
||||
const _err = new Error('kaboom');
|
||||
console.log('Setting up error handler on socket...');
|
||||
sock.on('error', common.mustCall((err) => {
|
||||
console.log('Socket error handler called with:', err.message);
|
||||
assert.strictEqual(err, _err);
|
||||
}));
|
||||
console.log('Throwing error...');
|
||||
throw _err;
|
||||
}));
|
||||
|
||||
console.log('Starting server...');
|
||||
server.listen(0, common.mustCall(() => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
console.log('Creating client connection...');
|
||||
const sock = connect({
|
||||
port: server.address().port,
|
||||
host: server.address().host,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
|
||||
console.log('Setting up close handler on client socket...');
|
||||
sock.on('close', common.mustCall(() => {
|
||||
console.log('Client socket closed');
|
||||
}));
|
||||
}));
|
||||
@@ -0,0 +1,88 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
// Test that `tls.Server` constructor options are passed to the parent
|
||||
// constructor.
|
||||
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tls = require('tls');
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
};
|
||||
|
||||
{
|
||||
console.log('Test case 1: Default options');
|
||||
const server = tls.createServer(options, common.mustCall((socket) => {
|
||||
console.log('Server socket created with default options');
|
||||
console.log('socket.allowHalfOpen:', socket.allowHalfOpen);
|
||||
console.log('socket.isPaused():', socket.isPaused());
|
||||
assert.strictEqual(socket.allowHalfOpen, false);
|
||||
assert.strictEqual(socket.isPaused(), false);
|
||||
}));
|
||||
|
||||
console.log('Server default options:');
|
||||
console.log('server.allowHalfOpen:', server.allowHalfOpen);
|
||||
console.log('server.pauseOnConnect:', server.pauseOnConnect);
|
||||
assert.strictEqual(server.allowHalfOpen, false);
|
||||
assert.strictEqual(server.pauseOnConnect, false);
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
const socket = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(() => {
|
||||
console.log('Client connected');
|
||||
socket.end();
|
||||
}));
|
||||
|
||||
socket.on('close', () => {
|
||||
console.log('Client socket closed');
|
||||
server.close();
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
console.log('\nTest case 2: Custom options');
|
||||
const server = tls.createServer({
|
||||
allowHalfOpen: true,
|
||||
pauseOnConnect: true,
|
||||
...options
|
||||
}, common.mustCall((socket) => {
|
||||
console.log('Server socket created with custom options');
|
||||
console.log('socket.allowHalfOpen:', socket.allowHalfOpen);
|
||||
console.log('socket.isPaused():', socket.isPaused());
|
||||
assert.strictEqual(socket.allowHalfOpen, true);
|
||||
assert.strictEqual(socket.isPaused(), true);
|
||||
socket.on('end', socket.end);
|
||||
}));
|
||||
|
||||
console.log('Server custom options:');
|
||||
console.log('server.allowHalfOpen:', server.allowHalfOpen);
|
||||
console.log('server.pauseOnConnect:', server.pauseOnConnect);
|
||||
assert.strictEqual(server.allowHalfOpen, true);
|
||||
assert.strictEqual(server.pauseOnConnect, true);
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
const socket = tls.connect({
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
}, common.mustCall(() => {
|
||||
console.log('Client connected');
|
||||
socket.end();
|
||||
}));
|
||||
|
||||
socket.on('close', () => {
|
||||
console.log('Client socket closed');
|
||||
server.close();
|
||||
});
|
||||
}));
|
||||
}
|
||||
74
test/js/node/test/parallel/test-tls-server-setkeycert.js
Normal file
74
test/js/node/test/parallel/test-tls-server-setkeycert.js
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const { X509Certificate } = require('crypto');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const altKeyCert = {
|
||||
key: fixtures.readKey('agent2-key.pem'),
|
||||
cert: fixtures.readKey('agent2-cert.pem'),
|
||||
minVersion: 'TLSv1.2',
|
||||
};
|
||||
|
||||
console.log('altKeyCert:', altKeyCert);
|
||||
|
||||
const altKeyCertVals = [
|
||||
altKeyCert,
|
||||
tls.createSecureContext(altKeyCert),
|
||||
];
|
||||
|
||||
console.log('altKeyCertVals length:', altKeyCertVals.length);
|
||||
|
||||
(function next() {
|
||||
if (!altKeyCertVals.length) {
|
||||
console.log('No more altKeyCertVals to process');
|
||||
return;
|
||||
}
|
||||
const altKeyCertVal = altKeyCertVals.shift();
|
||||
console.log('Processing altKeyCertVal:', altKeyCertVal);
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
minVersion: 'TLSv1.3',
|
||||
ALPNCallback: common.mustCall(function({ servername, protocols }) {
|
||||
console.log('ALPNCallback called with:', { servername, protocols });
|
||||
this.setKeyCert(altKeyCertVal);
|
||||
assert.deepStrictEqual(protocols, ['acme-tls/1']);
|
||||
return protocols[0];
|
||||
}),
|
||||
};
|
||||
|
||||
console.log('Creating server with options:', options);
|
||||
|
||||
tls.createServer(options, (s) => s.end()).listen(0, function() {
|
||||
console.log('Server listening on port:', this.address().port);
|
||||
|
||||
this.on('connection', common.mustCall((socket) => {
|
||||
console.log('Connection received');
|
||||
this.close();
|
||||
}));
|
||||
|
||||
tls.connect({
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
ALPNProtocols: ['acme-tls/1'],
|
||||
}, common.mustCall(function() {
|
||||
console.log('Client connected');
|
||||
assert.strictEqual(this.getProtocol(), 'TLSv1.3');
|
||||
const altCert = new X509Certificate(altKeyCert.cert);
|
||||
console.log('Comparing certificates:\n', this.getPeerX509Certificate().raw, '\n', altCert.raw);
|
||||
assert.strictEqual(
|
||||
this.getPeerX509Certificate().raw.equals(altCert.raw),
|
||||
true
|
||||
);
|
||||
this.end();
|
||||
next();
|
||||
}));
|
||||
});
|
||||
})();
|
||||
97
test/js/node/test/parallel/test-tls-set-secure-context.js
Normal file
97
test/js/node/test/parallel/test-tls-set-secure-context.js
Normal file
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto) {
|
||||
common.skip('missing crypto');
|
||||
}
|
||||
|
||||
// This test verifies the behavior of the tls setSecureContext() method.
|
||||
// It also verifies that existing connections are not disrupted when the
|
||||
// secure context is changed.
|
||||
|
||||
const assert = require('assert');
|
||||
const events = require('events');
|
||||
const https = require('https');
|
||||
const timers = require('timers/promises');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const credentialOptions = [
|
||||
{
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
ca: fixtures.readKey('ca1-cert.pem')
|
||||
},
|
||||
{
|
||||
key: fixtures.readKey('agent2-key.pem'),
|
||||
cert: fixtures.readKey('agent2-cert.pem'),
|
||||
ca: fixtures.readKey('ca2-cert.pem')
|
||||
},
|
||||
];
|
||||
let firstResponse;
|
||||
|
||||
const server = https.createServer(credentialOptions[0], (req, res) => {
|
||||
const id = +req.headers.id;
|
||||
|
||||
if (id === 1) {
|
||||
firstResponse = res;
|
||||
firstResponse.write('multi-');
|
||||
return;
|
||||
} else if (id === 4) {
|
||||
firstResponse.write('success-');
|
||||
}
|
||||
|
||||
res.end('success');
|
||||
});
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const { port } = server.address();
|
||||
const firstRequest = makeRequest(port, 1);
|
||||
|
||||
(async function makeRemainingRequests() {
|
||||
// Wait until the first request is guaranteed to have been handled.
|
||||
while (!firstResponse) {
|
||||
await timers.setImmediate();
|
||||
}
|
||||
|
||||
assert.strictEqual(await makeRequest(port, 2), 'success');
|
||||
|
||||
server.setSecureContext(credentialOptions[1]);
|
||||
firstResponse.write('request-');
|
||||
await assert.rejects(makeRequest(port, 3), {
|
||||
code: 'DEPTH_ZERO_SELF_SIGNED_CERT',
|
||||
});
|
||||
|
||||
server.setSecureContext(credentialOptions[0]);
|
||||
assert.strictEqual(await makeRequest(port, 4), 'success');
|
||||
|
||||
server.setSecureContext(credentialOptions[1]);
|
||||
firstResponse.end('fun!');
|
||||
await assert.rejects(makeRequest(port, 5), {
|
||||
code: 'DEPTH_ZERO_SELF_SIGNED_CERT',
|
||||
});
|
||||
|
||||
assert.strictEqual(await firstRequest, 'multi-request-success-fun!');
|
||||
server.close();
|
||||
})().then(common.mustCall());
|
||||
}));
|
||||
|
||||
async function makeRequest(port, id) {
|
||||
const options = {
|
||||
rejectUnauthorized: true,
|
||||
ca: credentialOptions[0].ca,
|
||||
servername: 'agent1',
|
||||
headers: { id },
|
||||
agent: new https.Agent()
|
||||
};
|
||||
|
||||
const req = https.get(`https://localhost:${port}`, options);
|
||||
|
||||
let errored = false;
|
||||
req.on('error', () => errored = true);
|
||||
req.on('finish', () => assert.strictEqual(errored, false));
|
||||
|
||||
const [res] = await events.once(req, 'response');
|
||||
res.setEncoding('utf8');
|
||||
let response = '';
|
||||
for await (const chunk of res) response += chunk;
|
||||
return response;
|
||||
}
|
||||
174
test/js/node/test/parallel/test-tls-sni-option.js
Normal file
174
test/js/node/test/parallel/test-tls-sni-option.js
Normal file
@@ -0,0 +1,174 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
function loadPEM(n) {
|
||||
return fixtures.readKey(`${n}.pem`);
|
||||
}
|
||||
|
||||
const serverOptions = {
|
||||
key: loadPEM('agent2-key'),
|
||||
cert: loadPEM('agent2-cert'),
|
||||
requestCert: true,
|
||||
rejectUnauthorized: false,
|
||||
SNICallback: function(servername, callback) {
|
||||
const context = SNIContexts[servername];
|
||||
|
||||
// Just to test asynchronous callback
|
||||
setTimeout(function() {
|
||||
if (context) {
|
||||
if (context.emptyRegression)
|
||||
callback(null, {});
|
||||
else
|
||||
callback(null, tls.createSecureContext(context));
|
||||
} else {
|
||||
callback(null, null);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
const SNIContexts = {
|
||||
'a.example.com': {
|
||||
key: loadPEM('agent1-key'),
|
||||
cert: loadPEM('agent1-cert'),
|
||||
ca: [ loadPEM('ca2-cert') ]
|
||||
},
|
||||
'b.example.com': {
|
||||
key: loadPEM('agent3-key'),
|
||||
cert: loadPEM('agent3-cert')
|
||||
},
|
||||
'c.another.com': {
|
||||
emptyRegression: true
|
||||
}
|
||||
};
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
key: loadPEM('agent1-key'),
|
||||
cert: loadPEM('agent1-cert'),
|
||||
ca: [loadPEM('ca1-cert')],
|
||||
servername: 'a.example.com',
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
true,
|
||||
{ sni: 'a.example.com', authorized: false },
|
||||
null,
|
||||
null);
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
key: loadPEM('agent4-key'),
|
||||
cert: loadPEM('agent4-cert'),
|
||||
ca: [loadPEM('ca1-cert')],
|
||||
servername: 'a.example.com',
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
true,
|
||||
{ sni: 'a.example.com', authorized: true },
|
||||
null,
|
||||
null);
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
key: loadPEM('agent2-key'),
|
||||
cert: loadPEM('agent2-cert'),
|
||||
ca: [loadPEM('ca2-cert')],
|
||||
servername: 'b.example.com',
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
true,
|
||||
{ sni: 'b.example.com', authorized: false },
|
||||
null,
|
||||
null);
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
key: loadPEM('agent3-key'),
|
||||
cert: loadPEM('agent3-cert'),
|
||||
ca: [loadPEM('ca1-cert')],
|
||||
servername: 'c.wrong.com',
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
false,
|
||||
{ sni: 'c.wrong.com', authorized: false },
|
||||
null,
|
||||
null);
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
key: loadPEM('agent3-key'),
|
||||
cert: loadPEM('agent3-cert'),
|
||||
ca: [loadPEM('ca1-cert')],
|
||||
servername: 'c.another.com',
|
||||
rejectUnauthorized: false
|
||||
},
|
||||
false,
|
||||
null,
|
||||
'Client network socket disconnected before secure TLS ' +
|
||||
'connection was established',
|
||||
'Invalid SNI context');
|
||||
|
||||
function test(options, clientResult, serverResult, clientError, serverError) {
|
||||
const server = tls.createServer(serverOptions, (c) => {
|
||||
assert.deepStrictEqual(
|
||||
serverResult,
|
||||
{ sni: c.servername, authorized: c.authorized }
|
||||
);
|
||||
});
|
||||
|
||||
if (serverResult) {
|
||||
assert(!serverError);
|
||||
server.on('tlsClientError', common.mustNotCall());
|
||||
} else {
|
||||
assert(serverError);
|
||||
server.on('tlsClientError', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, serverError);
|
||||
}));
|
||||
}
|
||||
|
||||
server.listen(0, () => {
|
||||
options.port = server.address().port;
|
||||
const client = tls.connect(options, () => {
|
||||
const result = client.authorizationError &&
|
||||
(client.authorizationError === 'ERR_TLS_CERT_ALTNAME_INVALID');
|
||||
assert.strictEqual(result, clientResult);
|
||||
client.end();
|
||||
});
|
||||
|
||||
client.on('close', common.mustCall(() => server.close()));
|
||||
|
||||
if (clientError)
|
||||
client.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, clientError);
|
||||
}));
|
||||
else
|
||||
client.on('error', common.mustNotCall());
|
||||
});
|
||||
}
|
||||
56
test/js/node/test/parallel/test-tls-sni-servername.js
Normal file
56
test/js/node/test/parallel/test-tls-sni-servername.js
Normal file
@@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
// We could get the `tlsSocket.servername` even if the event of "tlsClientError"
|
||||
// is emitted.
|
||||
|
||||
const serverOptions = {
|
||||
requestCert: true,
|
||||
rejectUnauthorized: false,
|
||||
SNICallback: function(servername, callback) {
|
||||
if (servername === 'c.another.com') {
|
||||
callback(null, {});
|
||||
} else {
|
||||
callback(new Error('Invalid SNI context'), null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function test(options) {
|
||||
const server = tls.createServer(serverOptions, common.mustNotCall());
|
||||
|
||||
server.on('tlsClientError', common.mustCall((err, socket) => {
|
||||
assert.strictEqual(err.message, 'Invalid SNI context');
|
||||
// The `servername` should match.
|
||||
assert.strictEqual(socket.servername, options.servername);
|
||||
}));
|
||||
|
||||
server.listen(0, () => {
|
||||
options.port = server.address().port;
|
||||
const client = tls.connect(options, common.mustNotCall());
|
||||
|
||||
client.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'Client network socket' +
|
||||
' disconnected before secure TLS connection was established');
|
||||
}));
|
||||
|
||||
client.on('close', common.mustCall(() => server.close()));
|
||||
});
|
||||
}
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
servername: 'c.another.com',
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
servername: 'c.wrong.com',
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
24
test/js/node/test/parallel/test-tls-snicallback-error.js
Normal file
24
test/js/node/test/parallel/test-tls-snicallback-error.js
Normal file
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
|
||||
for (const SNICallback of ['fhqwhgads', 42, {}, []]) {
|
||||
assert.throws(() => {
|
||||
tls.createServer({ SNICallback });
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
new tls.TLSSocket(new net.Socket(), { isServer: true, SNICallback });
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
name: 'TypeError',
|
||||
});
|
||||
}
|
||||
91
test/js/node/test/parallel/test-tls-socket-close.js
Normal file
91
test/js/node/test/parallel/test-tls-socket-close.js
Normal file
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
const Countdown = require('../common/countdown');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const key = fixtures.readKey('agent2-key.pem');
|
||||
const cert = fixtures.readKey('agent2-cert.pem');
|
||||
|
||||
let serverTlsSocket;
|
||||
const tlsServer = tls.createServer({ cert, key }, (socket) => {
|
||||
console.log('TLS server received connection');
|
||||
serverTlsSocket = socket;
|
||||
socket.on('data', (chunk) => {
|
||||
console.log('TLS server received data:', chunk[0]);
|
||||
assert.strictEqual(chunk[0], 46);
|
||||
socket.write('.');
|
||||
});
|
||||
socket.on('close', () => {
|
||||
console.log('TLS server socket closed');
|
||||
dec();
|
||||
});
|
||||
});
|
||||
|
||||
// A plain net server, that manually passes connections to the TLS
|
||||
// server to be upgraded.
|
||||
let netSocket;
|
||||
let netSocketCloseEmitted = false;
|
||||
const netServer = net.createServer((socket) => {
|
||||
console.log('Net server received connection');
|
||||
netSocket = socket;
|
||||
tlsServer.emit('connection', socket);
|
||||
socket.on('close', common.mustCall(() => {
|
||||
console.log('Net socket closed');
|
||||
netSocketCloseEmitted = true;
|
||||
assert.strictEqual(serverTlsSocket.destroyed, true);
|
||||
}));
|
||||
}).listen(0, common.mustCall(() => {
|
||||
console.log('Net server listening on port:', netServer.address().port);
|
||||
connectClient(netServer);
|
||||
}));
|
||||
|
||||
const countdown = new Countdown(2, () => {
|
||||
console.log('Countdown finished, closing net server');
|
||||
netServer.close();
|
||||
});
|
||||
|
||||
// A client that connects, sends one message, and closes the raw connection:
|
||||
function connectClient(server) {
|
||||
console.log('Connecting client');
|
||||
const clientTlsSocket = tls.connect({
|
||||
host: 'localhost',
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
|
||||
clientTlsSocket.write('.');
|
||||
|
||||
clientTlsSocket.on('data', (chunk) => {
|
||||
console.log('Client received data:', chunk[0]);
|
||||
assert.strictEqual(chunk[0], 46);
|
||||
|
||||
console.log('Destroying net socket');
|
||||
netSocket.destroy();
|
||||
assert.strictEqual(netSocket.destroyed, true);
|
||||
|
||||
setImmediate(() => {
|
||||
console.log('Checking socket states in setImmediate:');
|
||||
console.log('netSocketCloseEmitted:', netSocketCloseEmitted);
|
||||
console.log('serverTlsSocket.destroyed:', serverTlsSocket.destroyed);
|
||||
// Close callbacks are executed after `setImmediate()` callbacks.
|
||||
assert.strictEqual(netSocketCloseEmitted, false);
|
||||
assert.strictEqual(serverTlsSocket.destroyed, false);
|
||||
});
|
||||
});
|
||||
|
||||
clientTlsSocket.on('close', () => {
|
||||
console.log('Client socket closed');
|
||||
dec();
|
||||
});
|
||||
}
|
||||
|
||||
function dec() {
|
||||
console.log('Decrementing countdown');
|
||||
countdown.dec();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
// Test that TLSSocket can take arrays of strings for ALPNProtocols.
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
|
||||
new tls.TLSSocket(null, {
|
||||
ALPNProtocols: ['http/1.1'],
|
||||
});
|
||||
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
|
||||
const server = net.createServer(common.mustCall((s) => {
|
||||
const tlsSocket = new tls.TLSSocket(s, {
|
||||
isServer: true,
|
||||
server,
|
||||
key,
|
||||
cert,
|
||||
ALPNProtocols: ['http/1.1'],
|
||||
});
|
||||
|
||||
tlsSocket.on('secure', common.mustCall(() => {
|
||||
assert.strictEqual(tlsSocket.alpnProtocol, 'http/1.1');
|
||||
tlsSocket.end();
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const alpnOpts = {
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false,
|
||||
ALPNProtocols: ['h2', 'http/1.1']
|
||||
};
|
||||
|
||||
tls.connect(alpnOpts, common.mustCall(function() {
|
||||
this.end();
|
||||
}));
|
||||
}));
|
||||
@@ -0,0 +1,88 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
// Test directly created TLS sockets and options.
|
||||
|
||||
const assert = require('assert');
|
||||
const {
|
||||
connect, keys, tls
|
||||
} = require(fixtures.path('tls-connect'));
|
||||
|
||||
test(undefined, (err) => {
|
||||
console.log('Test 1 - Error code:', err.code);
|
||||
assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
|
||||
});
|
||||
|
||||
test({}, (err) => {
|
||||
console.log('Test 2 - Error code:', err.code);
|
||||
assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
|
||||
});
|
||||
|
||||
test(
|
||||
{ secureContext: tls.createSecureContext({ ca: keys.agent1.ca }) },
|
||||
(err) => {
|
||||
console.log('Test 3 - Error:', err);
|
||||
assert.ifError(err);
|
||||
});
|
||||
|
||||
test(
|
||||
{ ca: keys.agent1.ca },
|
||||
(err) => {
|
||||
console.log('Test 4 - Error:', err);
|
||||
assert.ifError(err);
|
||||
});
|
||||
|
||||
// Secure context options, like ca, are ignored if a sec ctx is explicitly
|
||||
// provided.
|
||||
test(
|
||||
{ secureContext: tls.createSecureContext(), ca: keys.agent1.ca },
|
||||
(err) => {
|
||||
console.log('Test 5 - Error code:', err.code);
|
||||
assert.strictEqual(err.code,
|
||||
'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
|
||||
});
|
||||
|
||||
function test(client, callback) {
|
||||
console.log('Starting test with client options:', client);
|
||||
callback = common.mustCall(callback);
|
||||
connect({
|
||||
server: {
|
||||
key: keys.agent1.key,
|
||||
cert: keys.agent1.cert,
|
||||
},
|
||||
}, function(err, pair, cleanup) {
|
||||
console.log('Connection error:', err);
|
||||
assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
|
||||
let recv = '';
|
||||
pair.server.server.once('secureConnection', common.mustCall((conn) => {
|
||||
console.log('Secure connection established');
|
||||
conn.on('data', (data) => {
|
||||
console.log('Received data:', data.toString());
|
||||
recv += data;
|
||||
});
|
||||
conn.on('end', common.mustCall(() => {
|
||||
console.log('Connection ended, received:', recv);
|
||||
// Server sees nothing wrong with connection, even though the client's
|
||||
// authentication of the server cert failed.
|
||||
assert.strictEqual(recv, 'hello');
|
||||
cleanup();
|
||||
}));
|
||||
}));
|
||||
|
||||
// `new TLSSocket` doesn't support the 'secureConnect' event on client side,
|
||||
// and doesn't error if authentication failed. Caller must explicitly check
|
||||
// for failure.
|
||||
const socket = new tls.TLSSocket(null, client);
|
||||
console.log('Created new TLSSocket');
|
||||
socket.connect(pair.server.server.address().port)
|
||||
.on('connect', common.mustCall(function() {
|
||||
console.log('Socket connected');
|
||||
this.end('hello');
|
||||
}))
|
||||
.on('secure', common.mustCall(function() {
|
||||
console.log('Socket secure, verify error:', this.ssl.verifyError());
|
||||
callback(this.ssl.verifyError());
|
||||
}));
|
||||
});
|
||||
}
|
||||
45
test/js/node/test/parallel/test-tls-socket-destroy.js
Normal file
45
test/js/node/test/parallel/test-tls-socket-destroy.js
Normal file
@@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
|
||||
console.log('Creating secure context with key and cert');
|
||||
const secureContext = tls.createSecureContext({ key, cert });
|
||||
|
||||
const server = net.createServer(common.mustCall((conn) => {
|
||||
console.log('Server received connection');
|
||||
const options = { isServer: true, secureContext, server };
|
||||
const socket = new tls.TLSSocket(conn, options);
|
||||
socket.once('data', common.mustCall(() => {
|
||||
console.log('Server received data, destroying SSL and socket');
|
||||
socket._destroySSL(); // Should not crash.
|
||||
socket.destroy();
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
|
||||
server.listen(0, function() {
|
||||
console.log('Server listening on port:', this.address().port);
|
||||
const options = {
|
||||
port: this.address().port,
|
||||
rejectUnauthorized: false,
|
||||
};
|
||||
tls.connect(options, function() {
|
||||
console.log('Client connected successfully');
|
||||
this.write('*'.repeat(1 << 20)); // Write more data than fits in a frame.
|
||||
console.log('Client wrote data');
|
||||
this.on('error', (err) => {
|
||||
console.log('Client received error:', err.message);
|
||||
this.destroy();
|
||||
}); // Server closes connection on us.
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
const assert = require('assert');
|
||||
|
||||
const bonkers = Buffer.alloc(1024, 42);
|
||||
|
||||
const server = net.createServer(function(c) {
|
||||
console.log('Server: New connection received');
|
||||
setTimeout(function() {
|
||||
console.log('Server: Creating TLSSocket');
|
||||
const s = new tls.TLSSocket(c, {
|
||||
isServer: true,
|
||||
server: server
|
||||
});
|
||||
|
||||
s.on('error', common.mustCall(function(e) {
|
||||
console.log('Server: Error received:', e.message);
|
||||
assert.ok(e instanceof Error,
|
||||
'Instance of Error should be passed to error handler');
|
||||
assert.ok(
|
||||
/SSL routines:[^:]*:wrong version number/.test(
|
||||
e.message),
|
||||
'Expecting SSL unknown protocol');
|
||||
}));
|
||||
|
||||
s.on('close', function() {
|
||||
console.log('Server: Connection closed');
|
||||
server.close();
|
||||
s.destroy();
|
||||
});
|
||||
}, common.platformTimeout(200));
|
||||
}).listen(0, function() {
|
||||
console.log('Server: Listening on port', this.address().port);
|
||||
const c = net.connect({ port: this.address().port }, function() {
|
||||
console.log('Client: Connected, writing bonkers data');
|
||||
c.write(bonkers);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
// This is based on test-tls-securepair-fiftharg.js
|
||||
// for the deprecated `tls.createSecurePair()` variant.
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { duplexPair } = require('stream');
|
||||
|
||||
const [ clientSide, serverSide ] = duplexPair();
|
||||
new tls.TLSSocket(serverSide, {
|
||||
isServer: true,
|
||||
SNICallback: common.mustCall((servername, cb) => {
|
||||
assert.strictEqual(servername, 'www.google.com');
|
||||
})
|
||||
});
|
||||
|
||||
// Captured traffic from browser's request to https://www.google.com
|
||||
const sslHello = fixtures.readSync('google_ssl_hello.bin');
|
||||
|
||||
clientSide.write(sslHello);
|
||||
48
test/js/node/test/parallel/test-tls-starttls-server.js
Normal file
48
test/js/node/test/parallel/test-tls-starttls-server.js
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
// Test asynchronous SNI+OCSP on TLSSocket created with `server` set to
|
||||
// `net.Server` instead of `tls.Server`
|
||||
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const key = fixtures.readKey('agent1-key.pem');
|
||||
const cert = fixtures.readKey('agent1-cert.pem');
|
||||
|
||||
const server = net.createServer(common.mustCall((s) => {
|
||||
const tlsSocket = new tls.TLSSocket(s, {
|
||||
isServer: true,
|
||||
server: server,
|
||||
|
||||
secureContext: tls.createSecureContext({ key, cert }),
|
||||
|
||||
SNICallback: common.mustCall((hostname, callback) => {
|
||||
assert.strictEqual(hostname, 'test.test');
|
||||
|
||||
callback(null, null);
|
||||
})
|
||||
});
|
||||
|
||||
tlsSocket.on('secure', common.mustCall(() => {
|
||||
tlsSocket.end();
|
||||
server.close();
|
||||
}));
|
||||
})).listen(0, () => {
|
||||
const opts = {
|
||||
servername: 'test.test',
|
||||
port: server.address().port,
|
||||
rejectUnauthorized: false,
|
||||
requestOCSP: true
|
||||
};
|
||||
|
||||
tls.connect(opts, function() {
|
||||
this.end();
|
||||
});
|
||||
});
|
||||
92
test/js/node/test/parallel/test-tls-streamwrap-buffersize.js
Normal file
92
test/js/node/test/parallel/test-tls-streamwrap-buffersize.js
Normal file
@@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { duplexPair } = require('stream');
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
|
||||
// This test ensures that `bufferSize` also works for those tlsSockets
|
||||
// created from `socket` of `Duplex`, with which, TLSSocket will wrap
|
||||
// sockets in `StreamWrap`.
|
||||
{
|
||||
const iter = 10;
|
||||
console.log('Starting test with iter:', iter);
|
||||
|
||||
function createDuplex(port) {
|
||||
console.log('Creating duplex pair for port:', port);
|
||||
const [ clientSide, serverSide ] = duplexPair();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const socket = net.connect({
|
||||
port,
|
||||
}, common.mustCall(() => {
|
||||
console.log('Socket connected, setting up pipes');
|
||||
clientSide.pipe(socket);
|
||||
socket.pipe(clientSide);
|
||||
clientSide.on('close', common.mustCall(() => {
|
||||
console.log('Client side closed, destroying socket');
|
||||
socket.destroy();
|
||||
}));
|
||||
socket.on('close', common.mustCall(() => {
|
||||
console.log('Socket closed, destroying client side');
|
||||
clientSide.destroy();
|
||||
}));
|
||||
|
||||
resolve(serverSide);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
const server = tls.createServer({
|
||||
key: fixtures.readKey('agent2-key.pem'),
|
||||
cert: fixtures.readKey('agent2-cert.pem')
|
||||
}, common.mustCall((socket) => {
|
||||
console.log('Server received connection');
|
||||
let str = '';
|
||||
socket.setEncoding('utf-8');
|
||||
socket.on('data', (chunk) => {
|
||||
console.log('Server received chunk:', chunk);
|
||||
str += chunk;
|
||||
});
|
||||
|
||||
socket.on('end', common.mustCall(() => {
|
||||
console.log('Server received end, str length:', str.length);
|
||||
assert.strictEqual(str, 'a'.repeat(iter - 1));
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(() => {
|
||||
const { port } = server.address();
|
||||
console.log('Server listening on port:', port);
|
||||
createDuplex(port).then((socket) => {
|
||||
console.log('Duplex created, connecting TLS client');
|
||||
const client = tls.connect({
|
||||
socket,
|
||||
rejectUnauthorized: false,
|
||||
}, common.mustCall(() => {
|
||||
console.log('TLS client connected, initial bufferSize:', client.bufferSize);
|
||||
assert.strictEqual(client.bufferSize, 0);
|
||||
|
||||
for (let i = 1; i < iter; i++) {
|
||||
client.write('a');
|
||||
console.log('Wrote data, bufferSize:', client.bufferSize);
|
||||
assert.strictEqual(client.bufferSize, i);
|
||||
}
|
||||
|
||||
client.on('end', common.mustCall(() => {
|
||||
console.log('Client received end event');
|
||||
}));
|
||||
client.on('close', common.mustCall(() => {
|
||||
console.log('Client closed, final bufferSize:', client.bufferSize);
|
||||
assert.strictEqual(client.bufferSize, undefined);
|
||||
}));
|
||||
|
||||
client.end();
|
||||
}));
|
||||
});
|
||||
}));
|
||||
}
|
||||
135
test/js/node/test/parallel/test-tls-ticket-cluster.js
Normal file
135
test/js/node/test/parallel/test-tls-ticket-cluster.js
Normal file
@@ -0,0 +1,135 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const cluster = require('cluster');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const workerCount = 4;
|
||||
const expectedReqCount = 16;
|
||||
|
||||
if (cluster.isPrimary) {
|
||||
let listeningCount = 0;
|
||||
let reusedCount = 0;
|
||||
let reqCount = 0;
|
||||
let lastSession = null;
|
||||
let workerPort = null;
|
||||
|
||||
function shoot() {
|
||||
console.error('[primary] connecting',
|
||||
workerPort, 'session?', !!lastSession);
|
||||
const c = tls.connect(workerPort, {
|
||||
session: lastSession,
|
||||
rejectUnauthorized: false
|
||||
}, () => {
|
||||
c.on('end', c.end);
|
||||
}).on('close', () => {
|
||||
// Wait for close to shoot off another connection. We don't want to shoot
|
||||
// until a new session is allocated, if one will be. The new session is
|
||||
// not guaranteed on secureConnect (it depends on TLS1.2 vs TLS1.3), but
|
||||
// it is guaranteed to happen before the connection is closed.
|
||||
if (++reqCount === expectedReqCount) {
|
||||
Object.keys(cluster.workers).forEach(function(id) {
|
||||
cluster.workers[id].send('die');
|
||||
});
|
||||
} else {
|
||||
shoot();
|
||||
}
|
||||
}).once('session', (session) => {
|
||||
assert(!lastSession);
|
||||
lastSession = session;
|
||||
});
|
||||
|
||||
c.resume(); // See close_notify comment in server
|
||||
}
|
||||
|
||||
function fork() {
|
||||
const worker = cluster.fork();
|
||||
worker.on('message', ({ msg, port }) => {
|
||||
console.error('[primary] got %j', msg);
|
||||
if (msg === 'reused') {
|
||||
++reusedCount;
|
||||
} else if (msg === 'listening' && ++listeningCount === workerCount) {
|
||||
workerPort = port;
|
||||
shoot();
|
||||
}
|
||||
});
|
||||
|
||||
worker.on('exit', () => {
|
||||
console.error('[primary] worker died');
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
fork();
|
||||
}
|
||||
|
||||
process.on('exit', () => {
|
||||
assert.strictEqual(reqCount, expectedReqCount);
|
||||
assert.strictEqual(reusedCount + 1, reqCount);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const key = fixtures.readKey('rsa_private.pem');
|
||||
const cert = fixtures.readKey('rsa_cert.crt');
|
||||
|
||||
const options = { key, cert };
|
||||
|
||||
const server = tls.createServer(options, (c) => {
|
||||
console.error('[worker] connection reused?', c.isSessionReused());
|
||||
if (c.isSessionReused()) {
|
||||
process.send({ msg: 'reused' });
|
||||
} else {
|
||||
process.send({ msg: 'not-reused' });
|
||||
}
|
||||
// Used to just .end(), but that means client gets close_notify before
|
||||
// NewSessionTicket. Send data until that problem is solved.
|
||||
c.end('x');
|
||||
});
|
||||
|
||||
server.listen(0, () => {
|
||||
const { port } = server.address();
|
||||
process.send({
|
||||
msg: 'listening',
|
||||
port,
|
||||
});
|
||||
});
|
||||
|
||||
process.on('message', function listener(msg) {
|
||||
console.error('[worker] got %j', msg);
|
||||
if (msg === 'die') {
|
||||
server.close(() => {
|
||||
console.error('[worker] server close');
|
||||
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
process.on('exit', () => {
|
||||
console.error('[worker] exit');
|
||||
});
|
||||
26
test/js/node/test/parallel/test-tls-ticket-invalid-arg.js
Normal file
26
test/js/node/test/parallel/test-tls-ticket-invalid-arg.js
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto) {
|
||||
common.skip('missing crypto');
|
||||
}
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
const server = new tls.Server();
|
||||
|
||||
[null, undefined, 0, 1, 1n, Symbol(), {}, [], true, false, '', () => {}]
|
||||
.forEach((arg) =>
|
||||
server.setTicketKeys(arg)
|
||||
// assert.throws(
|
||||
// () => server.setTicketKeys(arg),
|
||||
// { code: 'ERR_INVALID_ARG_TYPE' }
|
||||
// )
|
||||
);
|
||||
|
||||
[new Uint8Array(1), Buffer.from([1]), new DataView(new ArrayBuffer(2))].forEach(
|
||||
(arg) =>
|
||||
assert.throws(() => {
|
||||
server.setTicketKeys(arg);
|
||||
}, /Session ticket keys must be a 48-byte buffer/)
|
||||
);
|
||||
51
test/js/node/test/parallel/test-tls-timeout-server.js
Normal file
51
test/js/node/test/parallel/test-tls-timeout-server.js
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const options = {
|
||||
key: fixtures.readKey('agent1-key.pem'),
|
||||
cert: fixtures.readKey('agent1-cert.pem'),
|
||||
handshakeTimeout: 50
|
||||
};
|
||||
|
||||
console.log('Creating TLS server with options:', options);
|
||||
|
||||
const server = tls.createServer(options, common.mustNotCall());
|
||||
|
||||
server.on('tlsClientError', common.mustCall(function(err, conn) {
|
||||
console.log('TLS client error occurred:', err.message);
|
||||
conn.destroy();
|
||||
server.close();
|
||||
}));
|
||||
|
||||
server.listen(0, common.mustCall(function() {
|
||||
console.log('Server listening on port:', this.address().port);
|
||||
net.connect({ host: '127.0.0.1', port: this.address().port });
|
||||
}));
|
||||
48
test/js/node/test/parallel/test-tls-wrap-econnreset-pipe.js
Normal file
48
test/js/node/test/parallel/test-tls-wrap-econnreset-pipe.js
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const net = require('net');
|
||||
const { fork } = require('child_process');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
|
||||
// Run in a child process because the PIPE file descriptor stays open until
|
||||
// Node.js completes, blocking the tmpdir and preventing cleanup.
|
||||
|
||||
if (process.argv[2] !== 'child') {
|
||||
// Parent
|
||||
tmpdir.refresh();
|
||||
|
||||
// Run test
|
||||
const child = fork(__filename, ['child'], { stdio: 'inherit' });
|
||||
child.on('exit', common.mustCall(function(code) {
|
||||
assert.strictEqual(code, 0);
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Child
|
||||
const server = net.createServer((c) => {
|
||||
c.end();
|
||||
}).listen(common.PIPE, common.mustCall(() => {
|
||||
let errored = false;
|
||||
tls.connect({ path: common.PIPE })
|
||||
.once('error', common.mustCall((e) => {
|
||||
assert.strictEqual(e.code, 'ECONNRESET');
|
||||
assert.strictEqual(e.path, common.PIPE);
|
||||
assert.strictEqual(e.port, undefined);
|
||||
assert.strictEqual(e.host, undefined);
|
||||
assert.strictEqual(e.localAddress, undefined);
|
||||
server.close();
|
||||
errored = true;
|
||||
}))
|
||||
.on('close', common.mustCall(() => {
|
||||
assert.strictEqual(errored, true);
|
||||
}));
|
||||
}));
|
||||
28
test/js/node/test/parallel/test-tls-wrap-event-emmiter.js
Normal file
28
test/js/node/test/parallel/test-tls-wrap-event-emmiter.js
Normal file
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
// Issue: https://github.com/nodejs/node/issues/3655
|
||||
// Test checks if we get exception instead of runtime error
|
||||
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
const TlsSocket = require('tls').TLSSocket;
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
|
||||
console.log('Creating new EventEmitter...');
|
||||
const emitter = new EventEmitter();
|
||||
console.log('EventEmitter created');
|
||||
|
||||
console.log('Attempting to create new TLSSocket with EventEmitter...');
|
||||
assert.throws(
|
||||
() => {
|
||||
console.log('Inside throws callback');
|
||||
new TlsSocket(emitter);
|
||||
console.log('TLSSocket created (this should not happen)');
|
||||
},
|
||||
TypeError
|
||||
);
|
||||
console.log('Successfully caught TypeError as expected');
|
||||
32
test/js/node/test/parallel/test-tls-writewrap-leak.js
Normal file
32
test/js/node/test/parallel/test-tls-writewrap-leak.js
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
|
||||
console.log('Creating server...');
|
||||
const server = net.createServer(common.mustCall((c) => {
|
||||
console.log('Server received connection, destroying it...');
|
||||
c.destroy();
|
||||
})).listen(0, common.mustCall(() => {
|
||||
console.log('Server listening on port:', server.address().port);
|
||||
console.log('Creating TLS client connection...');
|
||||
const c = tls.connect({ port: server.address().port });
|
||||
c.on('error', (err) => {
|
||||
console.log('TLS client received error', err);
|
||||
// Otherwise `.write()` callback won't be invoked.
|
||||
// c._undestroy();
|
||||
});
|
||||
|
||||
console.log('Attempting to write data...');
|
||||
c.write('hello', common.mustCall((err) => {
|
||||
console.log('Write callback called with error:', err);
|
||||
assert.strictEqual(err.code, 'ECANCELED');
|
||||
console.log('Closing server...');
|
||||
server.close();
|
||||
}));
|
||||
}));
|
||||
160
test/js/node/test/sequential/test-tls-session-timeout.js
Normal file
160
test/js/node/test/sequential/test-tls-session-timeout.js
Normal file
@@ -0,0 +1,160 @@
|
||||
// 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.
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
if (!common.hasCrypto) {
|
||||
common.skip('missing crypto');
|
||||
}
|
||||
|
||||
const { opensslCli } = require('../common/crypto');
|
||||
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
tmpdir.refresh();
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
const fixtures = require('../common/fixtures');
|
||||
|
||||
const key = fixtures.readKey('rsa_private.pem');
|
||||
const cert = fixtures.readKey('rsa_cert.crt');
|
||||
|
||||
{
|
||||
// Node.js should not allow setting negative timeouts since new versions of
|
||||
// OpenSSL do not handle those as users might expect
|
||||
|
||||
for (const sessionTimeout of [-1, -100, -(2 ** 31)]) {
|
||||
assert.throws(() => {
|
||||
tls.createServer({
|
||||
key: key,
|
||||
cert: cert,
|
||||
ca: [cert],
|
||||
sessionTimeout,
|
||||
maxVersion: 'TLSv1.2',
|
||||
});
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
message: 'The value of "options.sessionTimeout" is out of range. It ' +
|
||||
`must be >= 0 && <= ${2 ** 31 - 1}. Received ${sessionTimeout}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!opensslCli) {
|
||||
common.skip('node compiled without OpenSSL CLI.');
|
||||
}
|
||||
|
||||
doTest();
|
||||
|
||||
// This test consists of three TLS requests --
|
||||
// * The first one should result in a new connection because we don't have
|
||||
// a valid session ticket.
|
||||
// * The second one should result in connection resumption because we used
|
||||
// the session ticket we saved from the first connection.
|
||||
// * The third one should result in a new connection because the ticket
|
||||
// that we used has expired by now.
|
||||
|
||||
function doTest() {
|
||||
const fs = require('fs');
|
||||
const spawn = require('child_process').spawn;
|
||||
|
||||
const SESSION_TIMEOUT = 1;
|
||||
|
||||
const options = {
|
||||
key: key,
|
||||
cert: cert,
|
||||
ca: [cert],
|
||||
sessionTimeout: SESSION_TIMEOUT,
|
||||
maxVersion: 'TLSv1.2',
|
||||
};
|
||||
|
||||
// We need to store a sample session ticket in the fixtures directory because
|
||||
// `s_client` behaves incorrectly if we do not pass in both the `-sess_in`
|
||||
// and the `-sess_out` flags, and the `-sess_in` argument must point to a
|
||||
// file containing a proper serialization of a session ticket.
|
||||
// To avoid a source control diff, we copy the ticket to a temporary file.
|
||||
|
||||
const sessionFileName = (function() {
|
||||
const ticketFileName = 'tls-session-ticket.txt';
|
||||
const tmpPath = tmpdir.resolve(ticketFileName);
|
||||
fs.writeFileSync(tmpPath, fixtures.readSync(ticketFileName));
|
||||
return tmpPath;
|
||||
}());
|
||||
|
||||
// Expects a callback -- cb(connectionType : enum ['New'|'Reused'])
|
||||
|
||||
function Client(cb) {
|
||||
const flags = [
|
||||
's_client',
|
||||
'-connect', `localhost:${common.PORT}`,
|
||||
'-sess_in', sessionFileName,
|
||||
'-sess_out', sessionFileName,
|
||||
];
|
||||
const client = spawn(opensslCli, flags, {
|
||||
stdio: ['ignore', 'pipe', 'ignore']
|
||||
});
|
||||
|
||||
let clientOutput = '';
|
||||
client.stdout.on('data', (data) => {
|
||||
clientOutput += data.toString();
|
||||
});
|
||||
client.on('exit', (code) => {
|
||||
let connectionType;
|
||||
const grepConnectionType = (line) => {
|
||||
const matches = line.match(/(New|Reused), /);
|
||||
if (matches) {
|
||||
connectionType = matches[1];
|
||||
return true;
|
||||
}
|
||||
};
|
||||
const lines = clientOutput.split('\n');
|
||||
if (!lines.some(grepConnectionType)) {
|
||||
throw new Error('unexpected output from openssl client');
|
||||
}
|
||||
assert.strictEqual(code, 0);
|
||||
cb(connectionType);
|
||||
});
|
||||
}
|
||||
|
||||
const server = tls.createServer(options, (cleartext) => {
|
||||
cleartext.on('error', (er) => {
|
||||
if (er.code !== 'ECONNRESET')
|
||||
throw er;
|
||||
});
|
||||
cleartext.end();
|
||||
});
|
||||
|
||||
server.listen(common.PORT, () => {
|
||||
Client((connectionType) => {
|
||||
assert.strictEqual(connectionType, 'New');
|
||||
Client((connectionType) => {
|
||||
assert.strictEqual(connectionType, 'Reused');
|
||||
setTimeout(() => {
|
||||
Client((connectionType) => {
|
||||
assert.strictEqual(connectionType, 'New');
|
||||
server.close();
|
||||
});
|
||||
}, (SESSION_TIMEOUT + 1) * 1000);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user