11cb0ef41Sopenharmony_ci// Flags: --expose-internals
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci'use strict';
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciconst common = require('../common');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciif (!common.hasCrypto)
81cb0ef41Sopenharmony_ci  common.skip('missing crypto');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciconst assert = require('assert');
111cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
121cb0ef41Sopenharmony_ciconst h2 = require('http2');
131cb0ef41Sopenharmony_ciconst { kSocket } = require('internal/http2/util');
141cb0ef41Sopenharmony_ciconst tls = require('tls');
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cifunction loadKey(keyname) {
171cb0ef41Sopenharmony_ci  return fixtures.readKey(keyname, 'binary');
181cb0ef41Sopenharmony_ci}
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cifunction onStream(stream, headers) {
211cb0ef41Sopenharmony_ci  const socket = stream.session[kSocket];
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  assert(stream.session.encrypted);
241cb0ef41Sopenharmony_ci  assert.strictEqual(stream.session.alpnProtocol, 'h2');
251cb0ef41Sopenharmony_ci  const originSet = stream.session.originSet;
261cb0ef41Sopenharmony_ci  assert(Array.isArray(originSet));
271cb0ef41Sopenharmony_ci  assert.strictEqual(originSet[0],
281cb0ef41Sopenharmony_ci                     `https://${socket.servername}:${socket.remotePort}`);
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci  assert(headers[':authority'].startsWith(socket.servername));
311cb0ef41Sopenharmony_ci  stream.respond({ 'content-type': 'application/json' });
321cb0ef41Sopenharmony_ci  stream.end(JSON.stringify({
331cb0ef41Sopenharmony_ci    servername: socket.servername,
341cb0ef41Sopenharmony_ci    alpnProtocol: socket.alpnProtocol
351cb0ef41Sopenharmony_ci  }));
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cifunction verifySecureSession(key, cert, ca, opts) {
391cb0ef41Sopenharmony_ci  const server = h2.createSecureServer({ cert, key });
401cb0ef41Sopenharmony_ci  server.on('stream', common.mustCall(onStream));
411cb0ef41Sopenharmony_ci  server.on('close', common.mustCall());
421cb0ef41Sopenharmony_ci  server.listen(0, common.mustCall(() => {
431cb0ef41Sopenharmony_ci    opts = opts || { };
441cb0ef41Sopenharmony_ci    opts.secureContext = tls.createSecureContext({ ca });
451cb0ef41Sopenharmony_ci    const client = h2.connect(`https://localhost:${server.address().port}`,
461cb0ef41Sopenharmony_ci                              opts);
471cb0ef41Sopenharmony_ci    // Verify that a 'secureConnect' listener is attached
481cb0ef41Sopenharmony_ci    assert.strictEqual(client.socket.listenerCount('secureConnect'), 1);
491cb0ef41Sopenharmony_ci    const req = client.request();
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci    client.on('connect', common.mustCall(() => {
521cb0ef41Sopenharmony_ci      assert(client.encrypted);
531cb0ef41Sopenharmony_ci      assert.strictEqual(client.alpnProtocol, 'h2');
541cb0ef41Sopenharmony_ci      const originSet = client.originSet;
551cb0ef41Sopenharmony_ci      assert(Array.isArray(originSet));
561cb0ef41Sopenharmony_ci      assert.strictEqual(originSet.length, 1);
571cb0ef41Sopenharmony_ci      assert.strictEqual(
581cb0ef41Sopenharmony_ci        originSet[0],
591cb0ef41Sopenharmony_ci        `https://${opts.servername || 'localhost'}:${server.address().port}`);
601cb0ef41Sopenharmony_ci    }));
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci    req.on('response', common.mustCall((headers) => {
631cb0ef41Sopenharmony_ci      assert.strictEqual(headers[':status'], 200);
641cb0ef41Sopenharmony_ci      assert.strictEqual(headers['content-type'], 'application/json');
651cb0ef41Sopenharmony_ci      assert(headers.date);
661cb0ef41Sopenharmony_ci    }));
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci    let data = '';
691cb0ef41Sopenharmony_ci    req.setEncoding('utf8');
701cb0ef41Sopenharmony_ci    req.on('data', (d) => data += d);
711cb0ef41Sopenharmony_ci    req.on('end', common.mustCall(() => {
721cb0ef41Sopenharmony_ci      const jsonData = JSON.parse(data);
731cb0ef41Sopenharmony_ci      assert.strictEqual(jsonData.servername,
741cb0ef41Sopenharmony_ci                         opts.servername || 'localhost');
751cb0ef41Sopenharmony_ci      assert.strictEqual(jsonData.alpnProtocol, 'h2');
761cb0ef41Sopenharmony_ci      server.close(common.mustSucceed());
771cb0ef41Sopenharmony_ci      client[kSocket].destroy();
781cb0ef41Sopenharmony_ci    }));
791cb0ef41Sopenharmony_ci  }));
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci// The server can be connected as 'localhost'.
831cb0ef41Sopenharmony_civerifySecureSession(
841cb0ef41Sopenharmony_ci  loadKey('agent8-key.pem'),
851cb0ef41Sopenharmony_ci  loadKey('agent8-cert.pem'),
861cb0ef41Sopenharmony_ci  loadKey('fake-startcom-root-cert.pem'));
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci// Custom servername is specified.
891cb0ef41Sopenharmony_civerifySecureSession(
901cb0ef41Sopenharmony_ci  loadKey('agent1-key.pem'),
911cb0ef41Sopenharmony_ci  loadKey('agent1-cert.pem'),
921cb0ef41Sopenharmony_ci  loadKey('ca1-cert.pem'),
931cb0ef41Sopenharmony_ci  { servername: 'agent1' });
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_civerifySecureSession(
961cb0ef41Sopenharmony_ci  loadKey('agent8-key.pem'),
971cb0ef41Sopenharmony_ci  loadKey('agent8-cert.pem'),
981cb0ef41Sopenharmony_ci  loadKey('fake-startcom-root-cert.pem'),
991cb0ef41Sopenharmony_ci  { servername: '' });
100