• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3if (!common.hasCrypto)
4  common.skip('missing crypto');
5
6const assert = require('assert');
7const tls = require('tls');
8const net = require('net');
9const fixtures = require('../common/fixtures');
10
11// Regression test for https://github.com/nodejs/node/issues/8074
12//
13// This test has a dependency on the order in which the TCP connection is made,
14// and TLS server handshake completes. It assumes those server side events occur
15// before the client side write callback, which is not guaranteed by the TLS
16// API. It usually passes with TLS1.3, but TLS1.3 didn't exist at the time the
17// bug existed.
18//
19// Pin the test to TLS1.2, since the test shouldn't be changed in a way that
20// doesn't trigger a segfault in Node.js 7.7.3:
21//   https://github.com/nodejs/node/issues/13184#issuecomment-303700377
22tls.DEFAULT_MAX_VERSION = 'TLSv1.2';
23
24const key = fixtures.readKey('agent2-key.pem');
25const cert = fixtures.readKey('agent2-cert.pem');
26
27let tlsSocket;
28// tls server
29const tlsServer = tls.createServer({ cert, key }, (socket) => {
30  tlsSocket = socket;
31  socket.on('error', common.mustCall((error) => {
32    assert.strictEqual(error.code, 'EINVAL');
33    tlsServer.close();
34    netServer.close();
35  }));
36});
37
38let netSocket;
39// plain tcp server
40const netServer = net.createServer((socket) => {
41  // If client wants to use tls
42  tlsServer.emit('connection', socket);
43
44  netSocket = socket;
45}).listen(0, common.mustCall(function() {
46  connectClient(netServer);
47}));
48
49function connectClient(server) {
50  const tlsConnection = tls.connect({
51    host: 'localhost',
52    port: server.address().port,
53    rejectUnauthorized: false
54  });
55
56  tlsConnection.write('foo', 'utf8', common.mustCall(() => {
57    assert(netSocket);
58    netSocket.setTimeout(common.platformTimeout(10), common.mustCall(() => {
59      assert(tlsSocket);
60      // This breaks if TLSSocket is already managing the socket:
61      netSocket.destroy();
62      const interval = setInterval(() => {
63        // Checking this way allows us to do the write at a time that causes a
64        // segmentation fault (not always, but often) in Node.js 7.7.3 and
65        // earlier. If we instead, for example, wait on the `close` event, then
66        // it will not segmentation fault, which is what this test is all about.
67        if (tlsSocket._handle._parent.bytesRead === 0) {
68          tlsSocket.write('bar');
69          clearInterval(interval);
70        }
71      }, 1);
72    }));
73  }));
74  tlsConnection.on('error', (e) => {
75    // Tolerate the occasional ECONNRESET.
76    // Ref: https://github.com/nodejs/node/issues/13184
77    if (e.code !== 'ECONNRESET')
78      throw e;
79  });
80}
81