11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors. 21cb0ef41Sopenharmony_ci// 31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the 51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including 61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish, 71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit 81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the 91cb0ef41Sopenharmony_ci// following conditions: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included 121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE. 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci'use strict'; 231cb0ef41Sopenharmony_ciconst common = require('../common'); 241cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures'); 251cb0ef41Sopenharmony_ciif (!common.hasCrypto) 261cb0ef41Sopenharmony_ci common.skip('missing crypto'); 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci// Disable strict server certificate validation by the client 291cb0ef41Sopenharmony_ciprocess.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cicommon.expectWarning( 321cb0ef41Sopenharmony_ci 'Warning', 331cb0ef41Sopenharmony_ci 'Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to \'0\' ' + 341cb0ef41Sopenharmony_ci 'makes TLS connections and HTTPS requests insecure by disabling ' + 351cb0ef41Sopenharmony_ci 'certificate verification.' 361cb0ef41Sopenharmony_ci); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ciconst assert = require('assert'); 391cb0ef41Sopenharmony_ciconst https = require('https'); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_cifunction read(fname) { 421cb0ef41Sopenharmony_ci return fixtures.readKey(fname); 431cb0ef41Sopenharmony_ci} 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci// key1 is signed by ca1. 461cb0ef41Sopenharmony_ciconst key1 = read('agent1-key.pem'); 471cb0ef41Sopenharmony_ciconst cert1 = read('agent1-cert.pem'); 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci// key2 has a self signed cert 501cb0ef41Sopenharmony_ciconst key2 = read('agent2-key.pem'); 511cb0ef41Sopenharmony_ciconst cert2 = read('agent2-cert.pem'); 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci// key3 is signed by ca2. 541cb0ef41Sopenharmony_ciconst key3 = read('agent3-key.pem'); 551cb0ef41Sopenharmony_ciconst cert3 = read('agent3-cert.pem'); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ciconst ca1 = read('ca1-cert.pem'); 581cb0ef41Sopenharmony_ciconst ca2 = read('ca2-cert.pem'); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci// Different agents to use different CA lists. 611cb0ef41Sopenharmony_ci// this api is beyond bad. 621cb0ef41Sopenharmony_ciconst agent0 = new https.Agent(); 631cb0ef41Sopenharmony_ciconst agent1 = new https.Agent({ ca: [ca1] }); 641cb0ef41Sopenharmony_ciconst agent2 = new https.Agent({ ca: [ca2] }); 651cb0ef41Sopenharmony_ciconst agent3 = new https.Agent({ ca: [ca1, ca2] }); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ciconst options1 = { 681cb0ef41Sopenharmony_ci key: key1, 691cb0ef41Sopenharmony_ci cert: cert1 701cb0ef41Sopenharmony_ci}; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ciconst options2 = { 731cb0ef41Sopenharmony_ci key: key2, 741cb0ef41Sopenharmony_ci cert: cert2 751cb0ef41Sopenharmony_ci}; 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciconst options3 = { 781cb0ef41Sopenharmony_ci key: key3, 791cb0ef41Sopenharmony_ci cert: cert3 801cb0ef41Sopenharmony_ci}; 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciconst server1 = server(options1); 831cb0ef41Sopenharmony_ciconst server2 = server(options2); 841cb0ef41Sopenharmony_ciconst server3 = server(options3); 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cilet listenWait = 0; 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ciserver1.listen(0, listening()); 891cb0ef41Sopenharmony_ciserver2.listen(0, listening()); 901cb0ef41Sopenharmony_ciserver3.listen(0, listening()); 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ciconst responseErrors = {}; 931cb0ef41Sopenharmony_cilet pending = 0; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_cifunction server(options) { 971cb0ef41Sopenharmony_ci const s = https.createServer(options, handler); 981cb0ef41Sopenharmony_ci s.requests = []; 991cb0ef41Sopenharmony_ci s.expectCount = 0; 1001cb0ef41Sopenharmony_ci return s; 1011cb0ef41Sopenharmony_ci} 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_cifunction handler(req, res) { 1041cb0ef41Sopenharmony_ci this.requests.push(req.url); 1051cb0ef41Sopenharmony_ci res.statusCode = 200; 1061cb0ef41Sopenharmony_ci res.setHeader('foo', 'bar'); 1071cb0ef41Sopenharmony_ci res.end('hello, world\n'); 1081cb0ef41Sopenharmony_ci} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_cifunction listening() { 1111cb0ef41Sopenharmony_ci listenWait++; 1121cb0ef41Sopenharmony_ci return () => { 1131cb0ef41Sopenharmony_ci listenWait--; 1141cb0ef41Sopenharmony_ci if (listenWait === 0) { 1151cb0ef41Sopenharmony_ci allListening(); 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci }; 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_cifunction makeReq(path, port, error, host, ca) { 1211cb0ef41Sopenharmony_ci pending++; 1221cb0ef41Sopenharmony_ci const options = { port, path, ca }; 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci if (!ca) { 1251cb0ef41Sopenharmony_ci options.agent = agent0; 1261cb0ef41Sopenharmony_ci } else { 1271cb0ef41Sopenharmony_ci if (!Array.isArray(ca)) ca = [ca]; 1281cb0ef41Sopenharmony_ci if (ca.includes(ca1) && ca.includes(ca2)) { 1291cb0ef41Sopenharmony_ci options.agent = agent3; 1301cb0ef41Sopenharmony_ci } else if (ca.includes(ca1)) { 1311cb0ef41Sopenharmony_ci options.agent = agent1; 1321cb0ef41Sopenharmony_ci } else if (ca.includes(ca2)) { 1331cb0ef41Sopenharmony_ci options.agent = agent2; 1341cb0ef41Sopenharmony_ci } else { 1351cb0ef41Sopenharmony_ci options.agent = agent0; 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci if (host) { 1401cb0ef41Sopenharmony_ci options.headers = { host }; 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci const req = https.get(options); 1431cb0ef41Sopenharmony_ci const server = port === server1.address().port ? server1 : 1441cb0ef41Sopenharmony_ci port === server2.address().port ? server2 : 1451cb0ef41Sopenharmony_ci port === server3.address().port ? server3 : 1461cb0ef41Sopenharmony_ci null; 1471cb0ef41Sopenharmony_ci if (!server) throw new Error(`invalid port: ${port}`); 1481cb0ef41Sopenharmony_ci server.expectCount++; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci req.on('response', common.mustCall((res) => { 1511cb0ef41Sopenharmony_ci assert.strictEqual(res.connection.authorizationError, error); 1521cb0ef41Sopenharmony_ci responseErrors[path] = res.connection.authorizationError; 1531cb0ef41Sopenharmony_ci pending--; 1541cb0ef41Sopenharmony_ci if (pending === 0) { 1551cb0ef41Sopenharmony_ci server1.close(); 1561cb0ef41Sopenharmony_ci server2.close(); 1571cb0ef41Sopenharmony_ci server3.close(); 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci res.resume(); 1601cb0ef41Sopenharmony_ci })); 1611cb0ef41Sopenharmony_ci} 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_cifunction allListening() { 1641cb0ef41Sopenharmony_ci // Ok, ready to start the tests! 1651cb0ef41Sopenharmony_ci const port1 = server1.address().port; 1661cb0ef41Sopenharmony_ci const port2 = server2.address().port; 1671cb0ef41Sopenharmony_ci const port3 = server3.address().port; 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci // server1: host 'agent1', signed by ca1 1701cb0ef41Sopenharmony_ci makeReq('/inv1', port1, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); 1711cb0ef41Sopenharmony_ci makeReq('/inv1-ca1', port1, 'ERR_TLS_CERT_ALTNAME_INVALID', 1721cb0ef41Sopenharmony_ci null, ca1); 1731cb0ef41Sopenharmony_ci makeReq('/inv1-ca1ca2', port1, 'ERR_TLS_CERT_ALTNAME_INVALID', 1741cb0ef41Sopenharmony_ci null, [ca1, ca2]); 1751cb0ef41Sopenharmony_ci makeReq('/val1-ca1', port1, null, 'agent1', ca1); 1761cb0ef41Sopenharmony_ci makeReq('/val1-ca1ca2', port1, null, 'agent1', [ca1, ca2]); 1771cb0ef41Sopenharmony_ci makeReq('/inv1-ca2', port1, 1781cb0ef41Sopenharmony_ci 'UNABLE_TO_VERIFY_LEAF_SIGNATURE', 'agent1', ca2); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci // server2: self-signed, host = 'agent2' 1811cb0ef41Sopenharmony_ci // doesn't matter that thename matches, all of these will error. 1821cb0ef41Sopenharmony_ci makeReq('/inv2', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT'); 1831cb0ef41Sopenharmony_ci makeReq('/inv2-ca1', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT', 1841cb0ef41Sopenharmony_ci 'agent2', ca1); 1851cb0ef41Sopenharmony_ci makeReq('/inv2-ca1ca2', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT', 1861cb0ef41Sopenharmony_ci 'agent2', [ca1, ca2]); 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci // server3: host 'agent3', signed by ca2 1891cb0ef41Sopenharmony_ci makeReq('/inv3', port3, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); 1901cb0ef41Sopenharmony_ci makeReq('/inv3-ca2', port3, 'ERR_TLS_CERT_ALTNAME_INVALID', null, ca2); 1911cb0ef41Sopenharmony_ci makeReq('/inv3-ca1ca2', port3, 'ERR_TLS_CERT_ALTNAME_INVALID', 1921cb0ef41Sopenharmony_ci null, [ca1, ca2]); 1931cb0ef41Sopenharmony_ci makeReq('/val3-ca2', port3, null, 'agent3', ca2); 1941cb0ef41Sopenharmony_ci makeReq('/val3-ca1ca2', port3, null, 'agent3', [ca1, ca2]); 1951cb0ef41Sopenharmony_ci makeReq('/inv3-ca1', port3, 1961cb0ef41Sopenharmony_ci 'UNABLE_TO_VERIFY_LEAF_SIGNATURE', 'agent1', ca1); 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci} 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ciprocess.on('exit', () => { 2011cb0ef41Sopenharmony_ci assert.strictEqual(server1.requests.length, server1.expectCount); 2021cb0ef41Sopenharmony_ci assert.strictEqual(server2.requests.length, server2.expectCount); 2031cb0ef41Sopenharmony_ci assert.strictEqual(server3.requests.length, server3.expectCount); 2041cb0ef41Sopenharmony_ci}); 205