• 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');
24if (!common.hasCrypto)
25  common.skip('missing crypto');
26
27const assert = require('assert');
28const tls = require('tls');
29const fixtures = require('../common/fixtures');
30
31
32function loadPEM(n) {
33  return fixtures.readKey(`${n}.pem`);
34}
35
36const serverOptions = {
37  key: loadPEM('agent2-key'),
38  cert: loadPEM('agent2-cert')
39};
40
41const SNIContexts = {
42  'a.example.com': {
43    key: loadPEM('agent1-key'),
44    cert: loadPEM('agent1-cert')
45  },
46  'asterisk.test.com': {
47    key: loadPEM('agent3-key'),
48    cert: loadPEM('agent3-cert')
49  },
50  'chain.example.com': {
51    key: loadPEM('agent6-key'),
52    // NOTE: Contains ca3 chain cert
53    cert: loadPEM('agent6-cert')
54  }
55};
56
57test(
58  {
59    ca: [loadPEM('ca1-cert')],
60    servername: 'a.example.com'
61  },
62  true,
63  'a.example.com'
64);
65
66test(
67  {
68    ca: [loadPEM('ca2-cert')],
69    servername: 'b.test.com',
70  },
71  true,
72  'b.test.com'
73);
74
75test(
76  {
77    ca: [loadPEM('ca2-cert')],
78    servername: 'a.b.test.com',
79  },
80  false,
81  'a.b.test.com'
82);
83
84test(
85  {
86    ca: [loadPEM('ca1-cert')],
87    servername: 'c.wrong.com',
88  },
89  false,
90  'c.wrong.com'
91);
92
93test(
94  {
95    ca: [loadPEM('ca1-cert')],
96    servername: 'chain.example.com',
97  },
98  true,
99  'chain.example.com'
100);
101
102function test(options, clientResult, serverResult) {
103  const server = tls.createServer(serverOptions, (c) => {
104    assert.strictEqual(c.servername, serverResult);
105    assert.strictEqual(c.authorized, false);
106  });
107
108  server.addContext('a.example.com', SNIContexts['a.example.com']);
109  server.addContext('*.test.com', SNIContexts['asterisk.test.com']);
110  server.addContext('chain.example.com', SNIContexts['chain.example.com']);
111
112  server.on('tlsClientError', common.mustNotCall());
113
114  server.listen(0, () => {
115    const client = tls.connect({
116      ...options,
117      port: server.address().port,
118      rejectUnauthorized: false
119    }, () => {
120      const result = client.authorizationError &&
121        (client.authorizationError === 'ERR_TLS_CERT_ALTNAME_INVALID');
122      assert.strictEqual(result, clientResult);
123      client.end();
124    });
125
126    client.on('close', common.mustCall(() => {
127      server.close();
128    }));
129  });
130}
131