summaryrefslogtreecommitdiff
path: root/test/fixtures/tls-connect.js
blob: 764bea77033d28fdb1e15f7cf4351e27726588bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// One shot call to connect a TLS client and server based on options to
// tls.createServer() and tls.connect(), so assertions can be made on both ends
// of the connection.
'use strict';

const common = require('../common');
// Check if Node was compiled --without-ssl and if so exit early
// as the require of tls will otherwise throw an Error.
if (!common.hasCrypto)
  common.skip('missing crypto');

const fixtures = require('../common/fixtures');
const tls = require('tls');
const util = require('util');

exports.assert = require('assert');
exports.debug = util.debuglog('test');
exports.tls = tls;

// Pre-load keys from common fixtures for ease of use by tests.
const keys = exports.keys = {
  agent1: load('agent1', 'ca1'),
  agent2: load('agent2', 'agent2'),
  agent3: load('agent3', 'ca2'),
  agent4: load('agent4', 'ca2'),
  agent5: load('agent5', 'ca2'),
  agent6: load('agent6', 'ca1'),
  agent7: load('agent7', 'fake-cnnic-root'),
  agent10: load('agent10', 'ca2'),
  ec10: load('ec10', 'ca5'),
  ec: load('ec', 'ec'),
};

// root is the self-signed root of the trust chain, not an intermediate ca.
function load(cert, root) {
  root = root || cert; // Assume self-signed if no issuer
  const id = {
    key: fixtures.readKey(cert + '-key.pem', 'binary'),
    cert: fixtures.readKey(cert + '-cert.pem', 'binary'),
    ca: fixtures.readKey(root + '-cert.pem', 'binary'),
  };
  return id;
}

exports.connect = function connect(options, callback) {
  callback = common.mustCall(callback);

  const server = {};
  const client = {};
  const pair = { server, client };

  try {
    tls.createServer(options.server, function(conn) {
      server.conn = conn;
      conn.pipe(conn);
      maybeCallback()
    }).listen(0, function() {
      server.server = this;

      const optClient = util._extend({
        port: this.address().port,
      }, options.client);

      try {
        tls.connect(optClient)
          .on('secureConnect', function() {
            client.conn = this;
            maybeCallback();
          })
          .on('error', function(err) {
            client.err = err;
            client.conn = this;
            maybeCallback();
          });
      } catch (err) {
        client.err = err;
        // The server won't get a connection, we are done.
        callback(err, pair, cleanup);
        callback = null;
      }
    }).on('tlsClientError', function(err, sock) {
      server.conn = sock;
      server.err = err;
      maybeCallback();
    });
  } catch (err) {
    // Invalid options can throw, report the error.
    pair.server.err = err;
    callback(err, pair, () => {});
  }

  function maybeCallback() {
    if (!callback)
      return;
    if (server.conn && (client.conn || client.err)) {
      const err = pair.client.err || pair.server.err;
      callback(err, pair, cleanup);
      callback = null;
    }
  }

  function cleanup() {
    if (server.server)
      server.server.close();
    if (client.conn)
      client.conn.end();
  }
}