tls: accept SecureContext object in server.addContext()

Do not call tls.createSecureContext() if the context provided
is already an instance of tls.SecureContext.

Fixes: https://github.com/nodejs/node/issues/47408
PR-URL: https://github.com/nodejs/node/pull/47570
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
HinataKah0 2023-04-26 14:39:00 +08:00 committed by GitHub
parent 11f97d4603
commit b54504c1d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 5 deletions

View File

@ -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).

View File

@ -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(

View File

@ -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();
}));
}));