Skip to content

Commit 1c29da8

Browse files
committed
tls: migrate C++ errors to internal/errors.js
* Throw ERR_TLS_SNI_FROM_SERVER when setting server names on a server-side socket instead of returning silently * Assert on wrap_->started and wrap_->ssl instead of throwing errors since these errors indicate that the user either uses private APIs, or monkey-patches internals, or hits a bug. PR-URL: #18125 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 9ffebea commit 1c29da8

File tree

5 files changed

+37
-21
lines changed

5 files changed

+37
-21
lines changed

doc/api/errors.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,12 @@ a hostname in the first parameter.
15301530
An excessive amount of TLS renegotiations is detected, which is a potential
15311531
vector for denial-of-service attacks.
15321532

1533+
<a id="ERR_TLS_SNI_FROM_SERVER"></a>
1534+
### ERR_TLS_SNI_FROM_SERVER
1535+
1536+
An attempt was made to issue Server Name Indication from a TLS server-side
1537+
socket, which is only valid from a client.
1538+
15331539
<a id="ERR_TLS_RENEGOTIATION_DISABLED"></a>
15341540
### ERR_TLS_RENEGOTIATION_DISABLED
15351541

lib/_tls_wrap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,11 @@ TLSSocket.prototype.setServername = function(name) {
660660
if (typeof name !== 'string') {
661661
throw new errors.Error('ERR_INVALID_ARG_TYPE', 'name', 'string');
662662
}
663+
664+
if (this._tlsOptions.isServer) {
665+
throw new errors.Error('ERR_TLS_SNI_FROM_SERVER');
666+
}
667+
663668
this._handle.setServername(name);
664669
};
665670

lib/internal/errors.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,8 @@ E('ERR_TLS_RENEGOTIATION_FAILED', 'Failed to renegotiate');
480480
E('ERR_TLS_REQUIRED_SERVER_NAME',
481481
'"servername" is required parameter for Server.addContext');
482482
E('ERR_TLS_SESSION_ATTACK', 'TLS session renegotiation attack detected');
483+
E('ERR_TLS_SNI_FROM_SERVER',
484+
'Cannot issue SNI from a TLS server-side socket');
483485
E('ERR_TRANSFORM_ALREADY_TRANSFORMING',
484486
'Calling transform done when still transforming');
485487
E('ERR_TRANSFORM_WITH_LENGTH_0',

src/tls_wrap.cc

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,11 @@ void TLSWrap::Receive(const FunctionCallbackInfo<Value>& args) {
225225

226226

227227
void TLSWrap::Start(const FunctionCallbackInfo<Value>& args) {
228-
Environment* env = Environment::GetCurrent(args);
229-
230228
TLSWrap* wrap;
231229
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
232230

233-
if (wrap->started_)
234-
return env->ThrowError("Already started.");
231+
CHECK(!wrap->started_);
232+
235233
wrap->started_ = true;
236234

237235
// Send ClientHello handshake
@@ -747,17 +745,13 @@ int TLSWrap::DoShutdown(ShutdownWrap* req_wrap) {
747745

748746

749747
void TLSWrap::SetVerifyMode(const FunctionCallbackInfo<Value>& args) {
750-
Environment* env = Environment::GetCurrent(args);
751-
752748
TLSWrap* wrap;
753749
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
754750

755751
CHECK_EQ(args.Length(), 2);
756752
CHECK(args[0]->IsBoolean());
757753
CHECK(args[1]->IsBoolean());
758-
759-
if (wrap->ssl_ == nullptr)
760-
return env->ThrowTypeError("SetVerifyMode after destroySSL");
754+
CHECK_NE(wrap->ssl_, nullptr);
761755

762756
int verify_mode;
763757
if (wrap->is_server()) {
@@ -785,10 +779,7 @@ void TLSWrap::EnableSessionCallbacks(
785779
const FunctionCallbackInfo<Value>& args) {
786780
TLSWrap* wrap;
787781
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
788-
if (wrap->ssl_ == nullptr) {
789-
return wrap->env()->ThrowTypeError(
790-
"EnableSessionCallbacks after destroySSL");
791-
}
782+
CHECK_NE(wrap->ssl_, nullptr);
792783
wrap->enable_session_callbacks();
793784
crypto::NodeBIO::FromBIO(wrap->enc_in_)->set_initial(kMaxHelloLength);
794785
wrap->hello_parser_.Start(SSLWrap<TLSWrap>::OnClientHello,
@@ -852,12 +843,8 @@ void TLSWrap::SetServername(const FunctionCallbackInfo<Value>& args) {
852843

853844
CHECK_EQ(args.Length(), 1);
854845
CHECK(args[0]->IsString());
855-
856-
if (wrap->started_)
857-
return env->ThrowError("Already started.");
858-
859-
if (!wrap->is_client())
860-
return;
846+
CHECK(!wrap->started_);
847+
CHECK(wrap->is_client());
861848

862849
CHECK_NE(wrap->ssl_, nullptr);
863850

test/parallel/test-tls-error-servername.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ const fixtures = require('../common/fixtures');
88
if (!common.hasCrypto)
99
common.skip('missing crypto');
1010

11-
const { connect } = require('tls');
11+
const { connect, TLSSocket } = require('tls');
1212
const makeDuplexPair = require('../common/duplexpair');
13-
const { clientSide } = makeDuplexPair();
13+
const { clientSide, serverSide } = makeDuplexPair();
1414

15+
const key = fixtures.readKey('agent1-key.pem');
16+
const cert = fixtures.readKey('agent1-cert.pem');
1517
const ca = fixtures.readKey('ca1-cert.pem');
1618

1719
const client = connect({
@@ -28,3 +30,17 @@ const client = connect({
2830
message: 'The "name" argument must be of type string'
2931
});
3032
});
33+
34+
const server = new TLSSocket(serverSide, {
35+
isServer: true,
36+
key,
37+
cert,
38+
ca
39+
});
40+
41+
common.expectsError(() => {
42+
server.setServername('localhost');
43+
}, {
44+
code: 'ERR_TLS_SNI_FROM_SERVER',
45+
message: 'Cannot issue SNI from a TLS server-side socket'
46+
});

0 commit comments

Comments
 (0)