• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const common = require('../common');
4const fixtures = require('../common/fixtures');
5
6const {
7  assert, connect, keys, tls
8} = require(fixtures.path('tls-connect'));
9
10// Use ec10 and agent10, they are the only identities with intermediate CAs.
11const client = keys.ec10;
12const server = keys.agent10;
13
14// The certificates aren't for "localhost", so override the identity check.
15function checkServerIdentity(hostname, cert) {
16  assert.strictEqual(hostname, 'localhost');
17  assert.strictEqual(cert.subject.CN, 'agent10.example.com');
18}
19
20// Split out the single end-entity cert and the subordinate CA for later use.
21split(client.cert, client);
22split(server.cert, server);
23
24function split(file, into) {
25  const certs = /([^]*END CERTIFICATE-----\r?\n)(-----BEGIN[^]*)/.exec(file);
26  assert.strictEqual(certs.length, 3);
27  into.single = certs[1];
28  into.subca = certs[2];
29}
30
31// Typical setup, nothing special, complete cert chains sent to peer.
32connect({
33  client: {
34    key: client.key,
35    cert: client.cert,
36    ca: server.ca,
37    checkServerIdentity,
38  },
39  server: {
40    key: server.key,
41    cert: server.cert,
42    ca: client.ca,
43    requestCert: true,
44  },
45}, function(err, pair, cleanup) {
46  assert.ifError(err);
47  return cleanup();
48});
49
50// As above, but without requesting client's cert.
51connect({
52  client: {
53    ca: server.ca,
54    checkServerIdentity,
55  },
56  server: {
57    key: server.key,
58    cert: server.cert,
59    ca: client.ca,
60  },
61}, function(err, pair, cleanup) {
62  assert.ifError(err);
63  return cleanup();
64});
65
66// Request cert from TLS1.2 client that doesn't have one.
67connect({
68  client: {
69    maxVersion: 'TLSv1.2',
70    ca: server.ca,
71    checkServerIdentity,
72  },
73  server: {
74    key: server.key,
75    cert: server.cert,
76    ca: client.ca,
77    requestCert: true,
78  },
79}, function(err, pair, cleanup) {
80  assert.strictEqual(pair.server.err.code,
81                     'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE');
82  assert.strictEqual(pair.client.err.code, 'ECONNRESET');
83  return cleanup();
84});
85
86// Request cert from TLS1.3 client that doesn't have one.
87if (tls.DEFAULT_MAX_VERSION === 'TLSv1.3') connect({
88  client: {
89    ca: server.ca,
90    checkServerIdentity,
91  },
92  server: {
93    key: server.key,
94    cert: server.cert,
95    ca: client.ca,
96    requestCert: true,
97  },
98}, function(err, pair, cleanup) {
99  assert.strictEqual(pair.server.err.code,
100                     'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE');
101
102  // TLS1.3 client completes handshake before server, and its only after the
103  // server handshakes, requests certs, gets back a zero-length list of certs,
104  // and sends a fatal Alert to the client that the client discovers there has
105  // been a fatal error.
106  pair.client.conn.once('error', common.mustCall((err) => {
107    assert.strictEqual(err.code, 'ERR_SSL_TLSV13_ALERT_CERTIFICATE_REQUIRED');
108    cleanup();
109  }));
110});
111
112// Typical configuration error, incomplete cert chains sent, we have to know the
113// peer's subordinate CAs in order to verify the peer.
114connect({
115  client: {
116    key: client.key,
117    cert: client.single,
118    ca: [server.ca, server.subca],
119    checkServerIdentity,
120  },
121  server: {
122    key: server.key,
123    cert: server.single,
124    ca: [client.ca, client.subca],
125    requestCert: true,
126  },
127}, function(err, pair, cleanup) {
128  assert.ifError(err);
129  return cleanup();
130});
131
132// Like above, but provide root CA and subordinate CA as multi-PEM.
133connect({
134  client: {
135    key: client.key,
136    cert: client.single,
137    ca: server.ca + '\n' + server.subca,
138    checkServerIdentity,
139  },
140  server: {
141    key: server.key,
142    cert: server.single,
143    ca: client.ca + '\n' + client.subca,
144    requestCert: true,
145  },
146}, function(err, pair, cleanup) {
147  assert.ifError(err);
148  return cleanup();
149});
150
151// Like above, but provide multi-PEM in an array.
152connect({
153  client: {
154    key: client.key,
155    cert: client.single,
156    ca: [server.ca + '\n' + server.subca],
157    checkServerIdentity,
158  },
159  server: {
160    key: server.key,
161    cert: server.single,
162    ca: [client.ca + '\n' + client.subca],
163    requestCert: true,
164  },
165}, function(err, pair, cleanup) {
166  assert.ifError(err);
167  return cleanup();
168});
169
170// Fail to complete server's chain
171connect({
172  client: {
173    ca: server.ca,
174    checkServerIdentity,
175  },
176  server: {
177    key: server.key,
178    cert: server.single,
179  },
180}, function(err, pair, cleanup) {
181  assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE');
182  return cleanup();
183});
184
185// Fail to complete client's chain.
186connect({
187  client: {
188    key: client.key,
189    cert: client.single,
190    ca: server.ca,
191    checkServerIdentity,
192  },
193  server: {
194    key: server.key,
195    cert: server.cert,
196    ca: client.ca,
197    requestCert: true,
198  },
199}, function(err, pair, cleanup) {
200  assert.ifError(pair.client.error);
201  assert.ifError(pair.server.error);
202  assert.strictEqual(err.code, 'ECONNRESET');
203  return cleanup();
204});
205
206// Fail to find CA for server.
207connect({
208  client: {
209    checkServerIdentity,
210  },
211  server: {
212    key: server.key,
213    cert: server.cert,
214  },
215}, function(err, pair, cleanup) {
216  assert.strictEqual(err.code, 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY');
217  return cleanup();
218});
219
220// Server sent their CA, but CA cannot be trusted if it is not locally known.
221connect({
222  client: {
223    checkServerIdentity,
224  },
225  server: {
226    key: server.key,
227    cert: server.cert + '\n' + server.ca,
228  },
229}, function(err, pair, cleanup) {
230  assert.strictEqual(err.code, 'SELF_SIGNED_CERT_IN_CHAIN');
231  return cleanup();
232});
233
234// Server sent their CA, wrongly, but its OK since we know the CA locally.
235connect({
236  client: {
237    checkServerIdentity,
238    ca: server.ca,
239  },
240  server: {
241    key: server.key,
242    cert: server.cert + '\n' + server.ca,
243  },
244}, function(err, pair, cleanup) {
245  assert.ifError(err);
246  return cleanup();
247});
248
249// Fail to complete client's chain.
250connect({
251  client: {
252    key: client.key,
253    cert: client.single,
254    ca: server.ca,
255    checkServerIdentity,
256  },
257  server: {
258    key: server.key,
259    cert: server.cert,
260    ca: client.ca,
261    requestCert: true,
262  },
263}, function(err, pair, cleanup) {
264  assert.strictEqual(err.code, 'ECONNRESET');
265  return cleanup();
266});
267
268// Fail to find CA for client.
269connect({
270  client: {
271    key: client.key,
272    cert: client.cert,
273    ca: server.ca,
274    checkServerIdentity,
275  },
276  server: {
277    key: server.key,
278    cert: server.cert,
279    requestCert: true,
280  },
281}, function(err, pair, cleanup) {
282  assert.strictEqual(err.code, 'ECONNRESET');
283  return cleanup();
284});
285
286// Confirm support for "BEGIN TRUSTED CERTIFICATE".
287connect({
288  client: {
289    key: client.key,
290    cert: client.cert,
291    ca: server.ca.replace(/CERTIFICATE/g, 'TRUSTED CERTIFICATE'),
292    checkServerIdentity,
293  },
294  server: {
295    key: server.key,
296    cert: server.cert,
297    ca: client.ca,
298    requestCert: true,
299  },
300}, function(err, pair, cleanup) {
301  assert.ifError(err);
302  return cleanup();
303});
304
305// Confirm support for "BEGIN TRUSTED CERTIFICATE".
306connect({
307  client: {
308    key: client.key,
309    cert: client.cert,
310    ca: server.ca,
311    checkServerIdentity,
312  },
313  server: {
314    key: server.key,
315    cert: server.cert,
316    ca: client.ca.replace(/CERTIFICATE/g, 'TRUSTED CERTIFICATE'),
317    requestCert: true,
318  },
319}, function(err, pair, cleanup) {
320  assert.ifError(err);
321  return cleanup();
322});
323
324// Confirm support for "BEGIN X509 CERTIFICATE".
325connect({
326  client: {
327    key: client.key,
328    cert: client.cert,
329    ca: server.ca.replace(/CERTIFICATE/g, 'X509 CERTIFICATE'),
330    checkServerIdentity,
331  },
332  server: {
333    key: server.key,
334    cert: server.cert,
335    ca: client.ca,
336    requestCert: true,
337  },
338}, function(err, pair, cleanup) {
339  assert.ifError(err);
340  return cleanup();
341});
342
343// Confirm support for "BEGIN X509 CERTIFICATE".
344connect({
345  client: {
346    key: client.key,
347    cert: client.cert,
348    ca: server.ca,
349    checkServerIdentity,
350  },
351  server: {
352    key: server.key,
353    cert: server.cert,
354    ca: client.ca.replace(/CERTIFICATE/g, 'X509 CERTIFICATE'),
355    requestCert: true,
356  },
357}, function(err, pair, cleanup) {
358  assert.ifError(err);
359  return cleanup();
360});
361