Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -1566,6 +1566,8 @@ function lookupAndConnect(self, options) {

// If host is an IP, skip performing a lookup
const addressType = isIP(host);
// Retain the host before the IP fast path for TLS session identity binding.
self._host = host;
if (addressType) {
defaultTriggerAsyncIdScope(self[async_id_symbol], process.nextTick, () => {
if (self.connecting)
Expand Down Expand Up @@ -1596,7 +1598,6 @@ function lookupAndConnect(self, options) {

debug('connect: find host', host);
debug('connect: dns options', dnsopts);
self._host = host;
const lookup = options.lookup || dns.lookup;

if (dnsopts.family !== 4 && dnsopts.family !== 6 && !localAddress && autoSelectFamily) {
Expand Down
99 changes: 99 additions & 0 deletions test/parallel/test-tls-session-reuse-provided-socket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Flags: --expose-internals
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

const assert = require('assert');
const fixtures = require('../common/fixtures');
const { hasMultiLocalhost } = require('../common/net');
const net = require('net');
const tls = require('tls');
const { once } = require('events');

async function connectWithSession(
socket, session, maxVersion, expectedReuse = true, servername,
) {
const tlsSocket = tls.connect({
socket,
session,
servername,
maxVersion,
rejectUnauthorized: false,
});
const close = once(tlsSocket, 'close');
tlsSocket.resume();
await once(tlsSocket, 'secureConnect');
assert.strictEqual(tlsSocket.isSessionReused(), expectedReuse);
await close;
}

async function connectAndCaptureSession(
port, maxVersion, host = '127.0.0.1', lookup,
) {
const socket = tls.connect({
host,
lookup,
port,
maxVersion,
rejectUnauthorized: false,
});
const close = once(socket, 'close');
const sessionPromise = once(socket, 'session').then(([session]) => session);
socket.resume();
await once(socket, 'secureConnect');
assert.strictEqual(socket.isSessionReused(), false);
const session = await sessionPromise;
assert(Buffer.isBuffer(session));
await close;
return session;
}

async function testVersion(maxVersion) {
const server = tls.createServer({
key: fixtures.readKey('agent1-key.pem'),
cert: fixtures.readKey('agent1-cert.pem'),
minVersion: maxVersion,
maxVersion,
}, (socket) => socket.end('ok'));

server.listen(0, '0.0.0.0');
await once(server, 'listening');
const { port } = server.address();
const session = await connectAndCaptureSession(port, maxVersion);

let socket = net.connect({ host: '127.0.0.1', port });
await once(socket, 'connect');
await connectWithSession(socket, session, maxVersion);

socket = net.connect({ host: '127.0.0.1', port });
await connectWithSession(socket, session, maxVersion);

if (hasMultiLocalhost()) {
socket = net.connect({ host: '127.0.0.2', port });
await connectWithSession(socket, session, maxVersion, false);
}

const lookup = (_hostname, _options, callback) => {
if (_options.all) {
callback(null, [{ address: '127.0.0.1', family: 4 }]);
} else {
callback(null, '127.0.0.1', 4);
}
};
const hostnameSession = await connectAndCaptureSession(
port, maxVersion, 'localhost', lookup);
socket = net.connect({ host: 'localhost', port, lookup });
await connectWithSession(socket, hostnameSession, maxVersion);

socket = net.connect({ host: '127.0.0.1', port });
await connectWithSession(socket, session, maxVersion, false, 'localhost');

server.close();
await once(server, 'close');
}

(async function() {
await testVersion('TLSv1.2');
await testVersion('TLSv1.3');
})().then(common.mustCall());
Loading