tls: set tlsSocket.servername as early as possible
This commit makes `TLSSocket` set the `servername` property on `SSL_CTX_set_tlsext_servername_callback` so that we could get it later even if errors happen. Fixes: https://github.com/nodejs/node/issues/27699 PR-URL: https://github.com/nodejs/node/pull/27759 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
This commit is contained in:
parent
78f2bb1c82
commit
d2cabee64c
@ -774,7 +774,10 @@ TLSSocket.prototype._finishInit = function() {
|
||||
return;
|
||||
|
||||
this.alpnProtocol = this._handle.getALPNNegotiatedProtocol();
|
||||
this.servername = this._handle.getServername();
|
||||
// The servername could be set by TLSWrap::SelectSNIContextCallback().
|
||||
if (this.servername === null) {
|
||||
this.servername = this._handle.getServername();
|
||||
}
|
||||
|
||||
debug('%s _finishInit',
|
||||
this._tlsOptions.isServer ? 'server' : 'client',
|
||||
|
@ -1033,6 +1033,14 @@ int TLSWrap::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
|
||||
Local<Object> object = p->object();
|
||||
Local<Value> ctx;
|
||||
|
||||
// Set the servername as early as possible
|
||||
Local<Object> owner = p->GetOwner();
|
||||
if (!owner->Set(env->context(),
|
||||
env->servername_string(),
|
||||
OneByteString(env->isolate(), servername)).FromMaybe(false)) {
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
||||
if (!object->Get(env->context(), env->sni_context_string()).ToLocal(&ctx))
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
|
||||
|
56
test/parallel/test-tls-sni-servername.js
Normal file
56
test/parallel/test-tls-sni-servername.js
Normal file
@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
if (!common.hasCrypto)
|
||||
common.skip('missing crypto');
|
||||
|
||||
const assert = require('assert');
|
||||
const tls = require('tls');
|
||||
|
||||
// We could get the `tlsSocket.servername` even if the event of "tlsClientError"
|
||||
// is emitted.
|
||||
|
||||
const serverOptions = {
|
||||
requestCert: true,
|
||||
rejectUnauthorized: false,
|
||||
SNICallback: function(servername, callback) {
|
||||
if (servername === 'c.another.com') {
|
||||
callback(null, {});
|
||||
} else {
|
||||
callback(new Error('Invalid SNI context'), null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function test(options) {
|
||||
const server = tls.createServer(serverOptions, common.mustNotCall());
|
||||
|
||||
server.on('tlsClientError', common.mustCall((err, socket) => {
|
||||
assert.strictEqual(err.message, 'Invalid SNI context');
|
||||
// The `servername` should match.
|
||||
assert.strictEqual(socket.servername, options.servername);
|
||||
}));
|
||||
|
||||
server.listen(0, () => {
|
||||
options.port = server.address().port;
|
||||
const client = tls.connect(options, common.mustNotCall());
|
||||
|
||||
client.on('error', common.mustCall((err) => {
|
||||
assert.strictEqual(err.message, 'Client network socket' +
|
||||
' disconnected before secure TLS connection was established');
|
||||
}));
|
||||
|
||||
client.on('close', common.mustCall(() => server.close()));
|
||||
});
|
||||
}
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
servername: 'c.another.com',
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
|
||||
test({
|
||||
port: undefined,
|
||||
servername: 'c.wrong.com',
|
||||
rejectUnauthorized: false
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user