node/test/parallel/test-quic-handshake.mjs
James M Snell 430f89eb8d quic: improve peer cert verification
On the client, add verifyPeer: 'auto', 'strict', and
'manual' modes. The 'strict' mode will reject invalid
certs at the handshake layer, while the 'manual' mode
allows the application to inspect the peer cert and decide
whether to trust it or not. The 'auto' mode is the default
and will reject invalid certs at a middle layer after the
onhandshake event.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode/Opus 4.6
PR-URL: https://github.com/nodejs/node/pull/63483
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-05-24 19:14:10 -07:00

65 lines
1.8 KiB
JavaScript

// Flags: --experimental-quic --no-warnings
import { hasQuic, skip, mustCall } from '../common/index.mjs';
import assert from 'node:assert';
import * as fixtures from '../common/fixtures.mjs';
const { readKey } = fixtures;
const { partialDeepStrictEqual, strictEqual, ok } = assert;
if (!hasQuic) {
skip('QUIC is not enabled');
}
// Import after the hasQuic check
const { listen, connect } = await import('node:quic');
const { createPrivateKey } = await import('node:crypto');
const key = createPrivateKey(readKey('agent1-key.pem'));
const cert = readKey('agent1-cert.pem');
const check = {
// The SNI value
servername: 'localhost',
// The selected ALPN protocol
protocol: 'quic-test',
// The negotiated cipher suite
cipher: 'TLS_AES_128_GCM_SHA256',
cipherVersion: 'TLSv1.3',
// No session ticket provided, so early data was not attempted
earlyDataAttempted: false,
earlyDataAccepted: false,
};
// The opened promise should resolve when the handshake is complete.
const serverOpened = Promise.withResolvers();
const serverEndpoint = await listen(mustCall((serverSession) => {
serverSession.opened.then((info) => {
partialDeepStrictEqual(info, check);
serverOpened.resolve();
serverSession.close();
}).then(mustCall());
}), {
sni: { '*': { keys: [key], certs: [cert] } },
alpn: ['quic-test'],
});
// Buffer is not detached.
strictEqual(cert.buffer.detached, false);
// The server must have an address to connect to after listen resolves.
ok(serverEndpoint.address !== undefined);
const clientSession = await connect(serverEndpoint.address, {
alpn: 'quic-test',
verifyPeer: 'manual',
});
const info = await clientSession.opened;
partialDeepStrictEqual(info, check);
await serverOpened.promise;
await clientSession.close();
await serverEndpoint.close();