• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23const common = require('../common');
24const fixtures = require('../common/fixtures');
25if (!common.hasCrypto)
26  common.skip('missing crypto');
27
28// Disable strict server certificate validation by the client
29process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
30
31common.expectWarning(
32  'Warning',
33  'Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to \'0\' ' +
34  'makes TLS connections and HTTPS requests insecure by disabling ' +
35  'certificate verification.'
36);
37
38const assert = require('assert');
39const https = require('https');
40
41function read(fname) {
42  return fixtures.readKey(fname);
43}
44
45// key1 is signed by ca1.
46const key1 = read('agent1-key.pem');
47const cert1 = read('agent1-cert.pem');
48
49// key2 has a self signed cert
50const key2 = read('agent2-key.pem');
51const cert2 = read('agent2-cert.pem');
52
53// key3 is signed by ca2.
54const key3 = read('agent3-key.pem');
55const cert3 = read('agent3-cert.pem');
56
57const ca1 = read('ca1-cert.pem');
58const ca2 = read('ca2-cert.pem');
59
60// Different agents to use different CA lists.
61// this api is beyond bad.
62const agent0 = new https.Agent();
63const agent1 = new https.Agent({ ca: [ca1] });
64const agent2 = new https.Agent({ ca: [ca2] });
65const agent3 = new https.Agent({ ca: [ca1, ca2] });
66
67const options1 = {
68  key: key1,
69  cert: cert1
70};
71
72const options2 = {
73  key: key2,
74  cert: cert2
75};
76
77const options3 = {
78  key: key3,
79  cert: cert3
80};
81
82const server1 = server(options1);
83const server2 = server(options2);
84const server3 = server(options3);
85
86let listenWait = 0;
87
88server1.listen(0, listening());
89server2.listen(0, listening());
90server3.listen(0, listening());
91
92const responseErrors = {};
93let pending = 0;
94
95
96function server(options) {
97  const s = https.createServer(options, handler);
98  s.requests = [];
99  s.expectCount = 0;
100  return s;
101}
102
103function handler(req, res) {
104  this.requests.push(req.url);
105  res.statusCode = 200;
106  res.setHeader('foo', 'bar');
107  res.end('hello, world\n');
108}
109
110function listening() {
111  listenWait++;
112  return () => {
113    listenWait--;
114    if (listenWait === 0) {
115      allListening();
116    }
117  };
118}
119
120function makeReq(path, port, error, host, ca) {
121  pending++;
122  const options = { port, path, ca };
123
124  if (!ca) {
125    options.agent = agent0;
126  } else {
127    if (!Array.isArray(ca)) ca = [ca];
128    if (ca.includes(ca1) && ca.includes(ca2)) {
129      options.agent = agent3;
130    } else if (ca.includes(ca1)) {
131      options.agent = agent1;
132    } else if (ca.includes(ca2)) {
133      options.agent = agent2;
134    } else {
135      options.agent = agent0;
136    }
137  }
138
139  if (host) {
140    options.headers = { host };
141  }
142  const req = https.get(options);
143  const server = port === server1.address().port ? server1 :
144    port === server2.address().port ? server2 :
145      port === server3.address().port ? server3 :
146        null;
147  if (!server) throw new Error(`invalid port: ${port}`);
148  server.expectCount++;
149
150  req.on('response', common.mustCall((res) => {
151    assert.strictEqual(res.connection.authorizationError, error);
152    responseErrors[path] = res.connection.authorizationError;
153    pending--;
154    if (pending === 0) {
155      server1.close();
156      server2.close();
157      server3.close();
158    }
159    res.resume();
160  }));
161}
162
163function allListening() {
164  // Ok, ready to start the tests!
165  const port1 = server1.address().port;
166  const port2 = server2.address().port;
167  const port3 = server3.address().port;
168
169  // server1: host 'agent1', signed by ca1
170  makeReq('/inv1', port1, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
171  makeReq('/inv1-ca1', port1, 'ERR_TLS_CERT_ALTNAME_INVALID',
172          null, ca1);
173  makeReq('/inv1-ca1ca2', port1, 'ERR_TLS_CERT_ALTNAME_INVALID',
174          null, [ca1, ca2]);
175  makeReq('/val1-ca1', port1, null, 'agent1', ca1);
176  makeReq('/val1-ca1ca2', port1, null, 'agent1', [ca1, ca2]);
177  makeReq('/inv1-ca2', port1,
178          'UNABLE_TO_VERIFY_LEAF_SIGNATURE', 'agent1', ca2);
179
180  // server2: self-signed, host = 'agent2'
181  // doesn't matter that thename matches, all of these will error.
182  makeReq('/inv2', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT');
183  makeReq('/inv2-ca1', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT',
184          'agent2', ca1);
185  makeReq('/inv2-ca1ca2', port2, 'DEPTH_ZERO_SELF_SIGNED_CERT',
186          'agent2', [ca1, ca2]);
187
188  // server3: host 'agent3', signed by ca2
189  makeReq('/inv3', port3, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
190  makeReq('/inv3-ca2', port3, 'ERR_TLS_CERT_ALTNAME_INVALID', null, ca2);
191  makeReq('/inv3-ca1ca2', port3, 'ERR_TLS_CERT_ALTNAME_INVALID',
192          null, [ca1, ca2]);
193  makeReq('/val3-ca2', port3, null, 'agent3', ca2);
194  makeReq('/val3-ca1ca2', port3, null, 'agent3', [ca1, ca2]);
195  makeReq('/inv3-ca1', port3,
196          'UNABLE_TO_VERIFY_LEAF_SIGNATURE', 'agent1', ca1);
197
198}
199
200process.on('exit', () => {
201  assert.strictEqual(server1.requests.length, server1.expectCount);
202  assert.strictEqual(server2.requests.length, server2.expectCount);
203  assert.strictEqual(server3.requests.length, server3.expectCount);
204});
205