11cb0ef41Sopenharmony_ci// One shot call to connect a TLS client and server based on options to 21cb0ef41Sopenharmony_ci// tls.createServer() and tls.connect(), so assertions can be made on both ends 31cb0ef41Sopenharmony_ci// of the connection. 41cb0ef41Sopenharmony_ci'use strict'; 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ciconst common = require('../common'); 71cb0ef41Sopenharmony_ci// Check if Node was compiled --without-ssl and if so exit early 81cb0ef41Sopenharmony_ci// as the require of tls will otherwise throw an Error. 91cb0ef41Sopenharmony_ciif (!common.hasCrypto) 101cb0ef41Sopenharmony_ci common.skip('missing crypto'); 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures'); 131cb0ef41Sopenharmony_ciconst tls = require('tls'); 141cb0ef41Sopenharmony_ciconst util = require('util'); 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciexports.assert = require('assert'); 171cb0ef41Sopenharmony_ciexports.debug = util.debuglog('test'); 181cb0ef41Sopenharmony_ciexports.tls = tls; 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ci// Pre-load keys from common fixtures for ease of use by tests. 211cb0ef41Sopenharmony_ciexports.keys = { 221cb0ef41Sopenharmony_ci agent1: load('agent1', 'ca1'), 231cb0ef41Sopenharmony_ci agent2: load('agent2', 'agent2'), 241cb0ef41Sopenharmony_ci agent3: load('agent3', 'ca2'), 251cb0ef41Sopenharmony_ci agent4: load('agent4', 'ca2'), 261cb0ef41Sopenharmony_ci agent5: load('agent5', 'ca2'), 271cb0ef41Sopenharmony_ci agent6: load('agent6', 'ca1'), 281cb0ef41Sopenharmony_ci agent7: load('agent7', 'fake-cnnic-root'), 291cb0ef41Sopenharmony_ci agent10: load('agent10', 'ca2'), 301cb0ef41Sopenharmony_ci ec10: load('ec10', 'ca5'), 311cb0ef41Sopenharmony_ci ec: load('ec', 'ec'), 321cb0ef41Sopenharmony_ci}; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci// `root` is the self-signed root of the trust chain, not an intermediate ca. 351cb0ef41Sopenharmony_cifunction load(cert, root) { 361cb0ef41Sopenharmony_ci root = root || cert; // Assume self-signed if no issuer. 371cb0ef41Sopenharmony_ci const id = { 381cb0ef41Sopenharmony_ci key: fixtures.readKey(cert + '-key.pem', 'binary'), 391cb0ef41Sopenharmony_ci cert: fixtures.readKey(cert + '-cert.pem', 'binary'), 401cb0ef41Sopenharmony_ci ca: fixtures.readKey(root + '-cert.pem', 'binary'), 411cb0ef41Sopenharmony_ci }; 421cb0ef41Sopenharmony_ci return id; 431cb0ef41Sopenharmony_ci} 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciexports.connect = function connect(options, callback) { 461cb0ef41Sopenharmony_ci callback = common.mustCall(callback); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci const server = {}; 491cb0ef41Sopenharmony_ci const client = {}; 501cb0ef41Sopenharmony_ci const pair = { server, client }; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci try { 531cb0ef41Sopenharmony_ci tls.createServer(options.server, function(conn) { 541cb0ef41Sopenharmony_ci server.conn = conn; 551cb0ef41Sopenharmony_ci conn.pipe(conn); 561cb0ef41Sopenharmony_ci maybeCallback(); 571cb0ef41Sopenharmony_ci }).listen(0, function() { 581cb0ef41Sopenharmony_ci server.server = this; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci const optClient = util._extend({ 611cb0ef41Sopenharmony_ci port: this.address().port, 621cb0ef41Sopenharmony_ci }, options.client); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci try { 651cb0ef41Sopenharmony_ci tls.connect(optClient) 661cb0ef41Sopenharmony_ci .on('secureConnect', function() { 671cb0ef41Sopenharmony_ci client.conn = this; 681cb0ef41Sopenharmony_ci maybeCallback(); 691cb0ef41Sopenharmony_ci }) 701cb0ef41Sopenharmony_ci .on('error', function(err) { 711cb0ef41Sopenharmony_ci client.err = err; 721cb0ef41Sopenharmony_ci client.conn = this; 731cb0ef41Sopenharmony_ci maybeCallback(); 741cb0ef41Sopenharmony_ci }); 751cb0ef41Sopenharmony_ci } catch (err) { 761cb0ef41Sopenharmony_ci client.err = err; 771cb0ef41Sopenharmony_ci // The server won't get a connection, we are done. 781cb0ef41Sopenharmony_ci callback(err, pair, cleanup); 791cb0ef41Sopenharmony_ci callback = null; 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci }).on('tlsClientError', function(err, sock) { 821cb0ef41Sopenharmony_ci server.conn = sock; 831cb0ef41Sopenharmony_ci server.err = err; 841cb0ef41Sopenharmony_ci maybeCallback(); 851cb0ef41Sopenharmony_ci }); 861cb0ef41Sopenharmony_ci } catch (err) { 871cb0ef41Sopenharmony_ci // Invalid options can throw, report the error. 881cb0ef41Sopenharmony_ci pair.server.err = err; 891cb0ef41Sopenharmony_ci callback(err, pair, () => {}); 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci function maybeCallback() { 931cb0ef41Sopenharmony_ci if (!callback) 941cb0ef41Sopenharmony_ci return; 951cb0ef41Sopenharmony_ci if (server.conn && client.conn) { 961cb0ef41Sopenharmony_ci const err = pair.client.err || pair.server.err; 971cb0ef41Sopenharmony_ci callback(err, pair, cleanup); 981cb0ef41Sopenharmony_ci callback = null; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci function cleanup() { 1031cb0ef41Sopenharmony_ci if (server.server) 1041cb0ef41Sopenharmony_ci server.server.close(); 1051cb0ef41Sopenharmony_ci if (client.conn) 1061cb0ef41Sopenharmony_ci client.conn.end(); 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci}; 109