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: nodejs#47408
PR-URL: nodejs#47570
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
HinataKah0 authored and yjl9903 committed Apr 28, 2023
1 parent 797e7ad commit 1a6da35
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 1a6da35

Please sign in to comment.