| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -627,6 +627,9 @@ added: v0.5.3 | |||
| 627 | 627 | The `server.addContext()` method adds a secure context that will be used if | |
| 628 | 628 | the client request's SNI name matches the supplied `hostname` (or wildcard). | |
| 629 | 629 | ||
| 630 | + When there are multiple matching contexts, the most recently added one is | ||
| 631 | + used. | ||
| 632 | + | ||
| 630 | 633 | ### `server.address()` | |
| 631 | 634 | <!-- YAML | |
| 632 | 635 | added: v0.6.0 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1458,7 +1458,8 @@ Server.prototype[EE.captureRejectionSymbol] = function( | |||
| 1458 | 1458 | function SNICallback(servername, callback) { | |
| 1459 | 1459 | const contexts = this.server._contexts; | |
| 1460 | 1460 | ||
| 1461 | - for (const elem of contexts) { | ||
| 1461 | + for (let i = contexts.length - 1; i >= 0; --i) { | ||
| 1462 | + const elem = contexts[i]; | ||
| 1462 | 1463 | if (RegExpPrototypeTest(elem[0], servername)) { | |
| 1463 | 1464 | callback(null, elem[1]); | |
| 1464 | 1465 | return; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,99 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const fixtures = require('../common/fixtures'); | ||
| 4 | + | ||
| 5 | + if (!common.hasCrypto) | ||
| 6 | + common.skip('missing crypto'); | ||
| 7 | + | ||
| 8 | + // This test ensures that when a TLS connection is established, the server | ||
| 9 | + // selects the most recently added SecureContext that matches the servername. | ||
| 10 | + | ||
| 11 | + const assert = require('assert'); | ||
| 12 | + const tls = require('tls'); | ||
| 13 | + | ||
| 14 | + function loadPEM(n) { | ||
| 15 | + return fixtures.readKey(`${n}.pem`); | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + const serverOptions = { | ||
| 19 | + key: loadPEM('agent2-key'), | ||
| 20 | + cert: loadPEM('agent2-cert'), | ||
| 21 | + requestCert: true, | ||
| 22 | + rejectUnauthorized: false, | ||
| 23 | + }; | ||
| 24 | + | ||
| 25 | + const badSecureContext = { | ||
| 26 | + key: loadPEM('agent1-key'), | ||
| 27 | + cert: loadPEM('agent1-cert'), | ||
| 28 | + ca: [ loadPEM('ca2-cert') ] | ||
| 29 | + }; | ||
| 30 | + | ||
| 31 | + const goodSecureContext = { | ||
| 32 | + key: loadPEM('agent1-key'), | ||
| 33 | + cert: loadPEM('agent1-cert'), | ||
| 34 | + ca: [ loadPEM('ca1-cert') ] | ||
| 35 | + }; | ||
| 36 | + | ||
| 37 | + const server = tls.createServer(serverOptions, (c) => { | ||
| 38 | + // The 'a' and 'b' subdomains are used to distinguish between client | ||
| 39 | + // connections. | ||
| 40 | + // Connection to subdomain 'a' is made when the 'bad' secure context is | ||
| 41 | + // the only one in use. | ||
| 42 | + if ('a.example.com' === c.servername) { | ||
| 43 | + assert.strictEqual(c.authorized, false); | ||
| 44 | + } | ||
| 45 | + // Connection to subdomain 'b' is made after the 'good' context has been | ||
| 46 | + // added. | ||
| 47 | + if ('b.example.com' === c.servername) { | ||
| 48 | + assert.strictEqual(c.authorized, true); | ||
| 49 | + } | ||
| 50 | + }); | ||
| 51 | + | ||
| 52 | + // 1. Add the 'bad' secure context. A connection using this context will not be | ||
| 53 | + // authorized. | ||
| 54 | + server.addContext('*.example.com', badSecureContext); | ||
| 55 | + | ||
| 56 | + server.listen(0, () => { | ||
| 57 | + const options = { | ||
| 58 | + port: server.address().port, | ||
| 59 | + key: loadPEM('agent1-key'), | ||
| 60 | + cert: loadPEM('agent1-cert'), | ||
| 61 | + ca: [loadPEM('ca1-cert')], | ||
| 62 | + servername: 'a.example.com', | ||
| 63 | + rejectUnauthorized: false, | ||
| 64 | + }; | ||
| 65 | + | ||
| 66 | + // 2. Make a connection using servername 'a.example.com'. Since a 'bad' | ||
| 67 | + // secure context is used, this connection should not be authorized. | ||
| 68 | + const client = tls.connect(options, () => { | ||
| 69 | + client.end(); | ||
| 70 | + }); | ||
| 71 | + | ||
| 72 | + client.on('close', common.mustCall(() => { | ||
| 73 | + // 3. Add a 'good' secure context. | ||
| 74 | + server.addContext('*.example.com', goodSecureContext); | ||
| 75 | + | ||
| 76 | + options.servername = 'b.example.com'; | ||
| 77 | + // 4. Make a connection using servername 'b.example.com'. This connection | ||
| 78 | + // should be authorized because the 'good' secure context is the most | ||
| 79 | + // recently added matching context. | ||
| 80 | + | ||
| 81 | + const other = tls.connect(options, () => { | ||
| 82 | + other.end(); | ||
| 83 | + }); | ||
| 84 | + | ||
| 85 | + other.on('close', common.mustCall(() => { | ||
| 86 | + // 5. Make another connection using servername 'b.example.com' to ensure | ||
| 87 | + // that the array of secure contexts is not reversed in place with each | ||
| 88 | + // SNICallback call, as someone might be tempted to refactor this piece of | ||
| 89 | + // code by using Array.prototype.reverse() method. | ||
| 90 | + const onemore = tls.connect(options, () => { | ||
| 91 | + onemore.end(); | ||
| 92 | + }); | ||
| 93 | + | ||
| 94 | + onemore.on('close', common.mustCall(() => { | ||
| 95 | + server.close(); | ||
| 96 | + })); | ||
| 97 | + })); | ||
| 98 | + })); | ||
| 99 | + }); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments