Skip to content

Commit

Permalink
tls: accept SecureContext object in server.addContext()
Browse files Browse the repository at this point in the history
Do not call tls.createSecureContext() if the context provided
is already an instance of tls.SecureContext.

Fixes: #47408
  • Loading branch information
HinataKah0 committed Apr 16, 2023
1 parent a777bbd commit 9660674
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 5 deletions.
7 changes: 4 additions & 3 deletions doc/api/tls.md
Original file line number Diff line number Diff line change
Expand Up @@ -728,9 +728,10 @@ added: v0.5.3
-->

* `hostname` {string} A SNI host name or wildcard (e.g. `'*'`)
* `context` {Object} An object containing any of the possible properties
from the [`tls.createSecureContext()`][] `options` arguments (e.g. `key`,
`cert`, `ca`, etc).
* `context` {Object|tls.SecureContext} An object containing any of the possible
properties from the [`tls.createSecureContext()`][] `options` arguments
(e.g. `key`, `cert`, `ca`, etc), or a TLS context object created with
[`tls.createSecureContext()`][] itself.

The `server.addContext()` method adds a secure context that will be used if
the client request's SNI name matches the supplied `hostname` (or wildcard).
Expand Down
6 changes: 4 additions & 2 deletions lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -1476,8 +1476,10 @@ Server.prototype.addContext = function(servername, context) {
RegExpPrototypeSymbolReplace(/([.^$+?\-\\[\]{}])/g, servername, '\\$1'),
'*', '[^.]*',
) + '$');
ArrayPrototypePush(this._contexts,
[re, tls.createSecureContext(context).context]);

const secureContext =
context instanceof common.SecureContext ? context : tls.createSecureContext(context);
ArrayPrototypePush(this._contexts, [re, secureContext.context]);
};

Server.prototype[EE.captureRejectionSymbol] = function(
Expand Down
75 changes: 75 additions & 0 deletions test/parallel/test-tls-add-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
'use strict';
const common = require('../common');

if (!common.hasCrypto)
common.skip('missing crypto');

const fixtures = require('../common/fixtures');
const assert = require('assert');
const tls = require('tls');

function loadPEM(n) {
return fixtures.readKey(`${n}.pem`);
}

const serverOptions = {
key: loadPEM('agent2-key'),
cert: loadPEM('agent2-cert'),
ca: [ loadPEM('ca2-cert') ],
requestCert: true,
rejectUnauthorized: false,
};

let connections = 0;

const server = tls.createServer(serverOptions, (c) => {
if (++connections === 3) {
server.close();
}
if (c.servername === 'unknowncontext') {
assert.strictEqual(c.authorized, false);
return;
}
assert.strictEqual(c.authorized, true);
});

const secureContext = {
key: loadPEM('agent1-key'),
cert: loadPEM('agent1-cert'),
ca: [ loadPEM('ca1-cert') ],
};
server.addContext('context1', secureContext);
server.addContext('context2', tls.createSecureContext(secureContext));

const clientOptionsBase = {
key: loadPEM('agent1-key'),
cert: loadPEM('agent1-cert'),
ca: [ loadPEM('ca1-cert') ],
rejectUnauthorized: false,
};

server.listen(0, common.mustCall(() => {
const client1 = tls.connect({
...clientOptionsBase,
port: server.address().port,
servername: 'context1',
}, common.mustCall(() => {
client1.end();
}));

const client2 = tls.connect({
...clientOptionsBase,
port: server.address().port,
servername: 'context2',
}, common.mustCall(() => {
client2.end();
}));

const client3 = tls.connect({
...clientOptionsBase,
port: server.address().port,
servername: 'unknowncontext',
}, common.mustCall(() => {
client3.end();
}));
}));

0 comments on commit 9660674

Please sign in to comment.