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