• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// One shot call to connect a TLS client and server based on options to
2// tls.createServer() and tls.connect(), so assertions can be made on both ends
3// of the connection.
4'use strict';
5
6const common = require('../common');
7// Check if Node was compiled --without-ssl and if so exit early
8// as the require of tls will otherwise throw an Error.
9if (!common.hasCrypto)
10  common.skip('missing crypto');
11
12const fixtures = require('../common/fixtures');
13const tls = require('tls');
14const util = require('util');
15
16exports.assert = require('assert');
17exports.debug = util.debuglog('test');
18exports.tls = tls;
19
20// Pre-load keys from common fixtures for ease of use by tests.
21exports.keys = {
22  agent1: load('agent1', 'ca1'),
23  agent2: load('agent2', 'agent2'),
24  agent3: load('agent3', 'ca2'),
25  agent4: load('agent4', 'ca2'),
26  agent5: load('agent5', 'ca2'),
27  agent6: load('agent6', 'ca1'),
28  agent7: load('agent7', 'fake-cnnic-root'),
29  agent10: load('agent10', 'ca2'),
30  ec10: load('ec10', 'ca5'),
31  ec: load('ec', 'ec'),
32};
33
34// `root` is the self-signed root of the trust chain, not an intermediate ca.
35function load(cert, root) {
36  root = root || cert; // Assume self-signed if no issuer.
37  const id = {
38    key: fixtures.readKey(cert + '-key.pem', 'binary'),
39    cert: fixtures.readKey(cert + '-cert.pem', 'binary'),
40    ca: fixtures.readKey(root + '-cert.pem', 'binary'),
41  };
42  return id;
43}
44
45exports.connect = function connect(options, callback) {
46  callback = common.mustCall(callback);
47
48  const server = {};
49  const client = {};
50  const pair = { server, client };
51
52  try {
53    tls.createServer(options.server, function(conn) {
54      server.conn = conn;
55      conn.pipe(conn);
56      maybeCallback();
57    }).listen(0, function() {
58      server.server = this;
59
60      const optClient = util._extend({
61        port: this.address().port,
62      }, options.client);
63
64      try {
65        tls.connect(optClient)
66          .on('secureConnect', function() {
67            client.conn = this;
68            maybeCallback();
69          })
70          .on('error', function(err) {
71            client.err = err;
72            client.conn = this;
73            maybeCallback();
74          });
75      } catch (err) {
76        client.err = err;
77        // The server won't get a connection, we are done.
78        callback(err, pair, cleanup);
79        callback = null;
80      }
81    }).on('tlsClientError', function(err, sock) {
82      server.conn = sock;
83      server.err = err;
84      maybeCallback();
85    });
86  } catch (err) {
87    // Invalid options can throw, report the error.
88    pair.server.err = err;
89    callback(err, pair, () => {});
90  }
91
92  function maybeCallback() {
93    if (!callback)
94      return;
95    if (server.conn && client.conn) {
96      const err = pair.client.err || pair.server.err;
97      callback(err, pair, cleanup);
98      callback = null;
99    }
100  }
101
102  function cleanup() {
103    if (server.server)
104      server.server.close();
105    if (client.conn)
106      client.conn.end();
107  }
108};
109