11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciif (!common.hasCrypto)
51cb0ef41Sopenharmony_ci  common.skip('missing crypto');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci// This test verifies the behavior of the tls setSecureContext() method.
81cb0ef41Sopenharmony_ci// It also verifies that existing connections are not disrupted when the
91cb0ef41Sopenharmony_ci// secure context is changed.
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ciconst assert = require('assert');
121cb0ef41Sopenharmony_ciconst events = require('events');
131cb0ef41Sopenharmony_ciconst https = require('https');
141cb0ef41Sopenharmony_ciconst timers = require('timers/promises');
151cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
161cb0ef41Sopenharmony_ciconst credentialOptions = [
171cb0ef41Sopenharmony_ci  {
181cb0ef41Sopenharmony_ci    key: fixtures.readKey('agent1-key.pem'),
191cb0ef41Sopenharmony_ci    cert: fixtures.readKey('agent1-cert.pem'),
201cb0ef41Sopenharmony_ci    ca: fixtures.readKey('ca1-cert.pem')
211cb0ef41Sopenharmony_ci  },
221cb0ef41Sopenharmony_ci  {
231cb0ef41Sopenharmony_ci    key: fixtures.readKey('agent2-key.pem'),
241cb0ef41Sopenharmony_ci    cert: fixtures.readKey('agent2-cert.pem'),
251cb0ef41Sopenharmony_ci    ca: fixtures.readKey('ca2-cert.pem')
261cb0ef41Sopenharmony_ci  },
271cb0ef41Sopenharmony_ci];
281cb0ef41Sopenharmony_cilet firstResponse;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciconst server = https.createServer(credentialOptions[0], (req, res) => {
311cb0ef41Sopenharmony_ci  const id = +req.headers.id;
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  if (id === 1) {
341cb0ef41Sopenharmony_ci    firstResponse = res;
351cb0ef41Sopenharmony_ci    firstResponse.write('multi-');
361cb0ef41Sopenharmony_ci    return;
371cb0ef41Sopenharmony_ci  } else if (id === 4) {
381cb0ef41Sopenharmony_ci    firstResponse.write('success-');
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  res.end('success');
421cb0ef41Sopenharmony_ci});
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => {
451cb0ef41Sopenharmony_ci  const { port } = server.address();
461cb0ef41Sopenharmony_ci  const firstRequest = makeRequest(port, 1);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  (async function makeRemainingRequests() {
491cb0ef41Sopenharmony_ci    // Wait until the first request is guaranteed to have been handled.
501cb0ef41Sopenharmony_ci    while (!firstResponse) {
511cb0ef41Sopenharmony_ci      await timers.setImmediate();
521cb0ef41Sopenharmony_ci    }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci    assert.strictEqual(await makeRequest(port, 2), 'success');
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci    server.setSecureContext(credentialOptions[1]);
571cb0ef41Sopenharmony_ci    firstResponse.write('request-');
581cb0ef41Sopenharmony_ci    const errorMessageRegex = common.hasOpenSSL3 ?
591cb0ef41Sopenharmony_ci      /^Error: self-signed certificate$/ :
601cb0ef41Sopenharmony_ci      /^Error: self signed certificate$/;
611cb0ef41Sopenharmony_ci    await assert.rejects(makeRequest(port, 3), errorMessageRegex);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci    server.setSecureContext(credentialOptions[0]);
641cb0ef41Sopenharmony_ci    assert.strictEqual(await makeRequest(port, 4), 'success');
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci    server.setSecureContext(credentialOptions[1]);
671cb0ef41Sopenharmony_ci    firstResponse.end('fun!');
681cb0ef41Sopenharmony_ci    await assert.rejects(makeRequest(port, 5), errorMessageRegex);
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci    assert.strictEqual(await firstRequest, 'multi-request-success-fun!');
711cb0ef41Sopenharmony_ci    server.close();
721cb0ef41Sopenharmony_ci  })().then(common.mustCall());
731cb0ef41Sopenharmony_ci}));
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ciasync function makeRequest(port, id) {
761cb0ef41Sopenharmony_ci  const options = {
771cb0ef41Sopenharmony_ci    rejectUnauthorized: true,
781cb0ef41Sopenharmony_ci    ca: credentialOptions[0].ca,
791cb0ef41Sopenharmony_ci    servername: 'agent1',
801cb0ef41Sopenharmony_ci    headers: { id },
811cb0ef41Sopenharmony_ci    agent: new https.Agent()
821cb0ef41Sopenharmony_ci  };
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  const req = https.get(`https://localhost:${port}`, options);
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  let errored = false;
871cb0ef41Sopenharmony_ci  req.on('error', () => errored = true);
881cb0ef41Sopenharmony_ci  req.on('finish', () => assert.strictEqual(errored, false));
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  const [res] = await events.once(req, 'response');
911cb0ef41Sopenharmony_ci  res.setEncoding('utf8');
921cb0ef41Sopenharmony_ci  let response = '';
931cb0ef41Sopenharmony_ci  for await (const chunk of res) response += chunk;
941cb0ef41Sopenharmony_ci  return response;
951cb0ef41Sopenharmony_ci}
96